【发布时间】:2021-05-27 08:50:35
【问题描述】:
我最近从 Google Bigquery 获取并整理了很多 reddit 数据。
数据集如下所示:
在将此数据传递给 word2vec 以创建词汇表并进行训练之前,我需要正确标记“body_cleaned”列。
我已经尝试使用手动创建的函数和 NLTK 的 word_tokenize 进行标记化,但现在我将重点放在使用 word_tokenize 上。
由于我的数据集比较大,接近 1200 万行,我不可能一次性打开数据集并对其执行功能。 Pandas 尝试将所有内容加载到 RAM 中,正如您所理解的那样,它会崩溃,即使在具有 24GB 内存的系统上也是如此。
我面临以下问题:
- 当我对数据集进行标记(使用 NTLK word_tokenize)时,如果我对整个数据集执行该函数,它会正确标记并且 word2vec 接受该输入并在其词汇表中正确学习/输出单词。
- 当我通过首先批处理数据帧并迭代它来标记数据集时,生成的标记列不是 word2vec 喜欢的;尽管 word2vec 使用超过 4 小时收集的数据训练其模型,但它所学习的词汇表由多种编码的单个字符以及表情符号组成,而不是单词。
为了解决这个问题,我创建了一小部分数据并尝试以两种不同的方式对该数据执行标记化:
- 知道我的计算机可以处理对数据集执行的操作,我只是这样做了:
reddit_subset = reddit_data[:50]
reddit_subset['tokens'] = reddit_subset['body_cleaned'].apply(lambda x: word_tokenize(x))
这实际上适用于 word2vec 并生成可以使用的模型。到目前为止很棒。
由于我无法一次性对如此庞大的数据集进行操作,因此我不得不对如何处理这个数据集进行创新。我的解决方案是批处理数据集并使用 Panda 自己的 batchsize 参数在小迭代中处理它。
我编写了以下函数来实现这一点:
def reddit_data_cleaning(filepath, batchsize=20000):
if batchsize:
df = pd.read_csv(filepath, encoding='utf-8', error_bad_lines=False, chunksize=batchsize, iterator=True, lineterminator='\n')
print("Beginning the data cleaning process!")
start_time = time.time()
flag = 1
chunk_num = 1
for chunk in df:
chunk[u'tokens'] = chunk[u'body_cleaned'].apply(lambda x: word_tokenize(x))
chunk_num += 1
if flag == 1:
chunk.dropna(how='any')
chunk = chunk[chunk['body_cleaned'] != 'deleted']
chunk = chunk[chunk['body_cleaned'] != 'removed']
print("Beginning writing a new file")
chunk.to_csv(str(filepath[:-4] + '_tokenized.csv'), mode='w+', index=None, header=True)
flag = 0
else:
chunk.dropna(how='any')
chunk = chunk[chunk['body_cleaned'] != 'deleted']
chunk = chunk[chunk['body_cleaned'] != 'removed']
print("Adding a chunk into an already existing file")
chunk.to_csv(str(filepath[:-4] + '_tokenized.csv'), mode='a', index=None, header=None)
end_time = time.time()
print("Processing has been completed in: ", (end_time - start_time), " seconds.")
虽然这段代码让我能够真正分块处理这个庞大的数据集并产生结果,否则我会因内存故障而崩溃,但我得到的结果不符合我的 word2vec 要求,让我很困惑原因。
我用上面的函数对Data子集进行同样的操作,比较两个函数的结果有什么不同,得到如下:
所需的结果在 new_tokens 列上,分块数据帧的函数会产生“tokens”列结果。
有谁更聪明地帮助我理解为什么相同的标记化函数会根据我对数据帧的迭代方式产生完全不同的结果?
如果您通读整个问题并坚持下去,我将不胜感激!
【问题讨论】:
标签: python pandas tokenize word2vec