在上一篇文章中,使用了logistic回归来对电影评论进行分类,消耗了2到3个小时,在使用网格搜索对50000条电影评论构建特征向量的时候计算成本是非常大的。在实际应用中,可能会遇见更大的数据集,如果直接把数据集加载到内存中,可能会超出计算机的最大内存,同时也会需要更久的训练时间。在这篇文章中,将介绍外存学习来处理大数据集,使用外存学习来处理50000条电影评论只需要1分钟。
在梯度下降算法中,我们有学习过随机梯度下降和批量梯度下降,每次通过一个或批量的训练数据来更新权重。而,外存学习与批量梯度下降的思想是一致的。使用sklearn的SGDClassifier的partial_fit函数来训练从本地磁盘读取的批量数据,来构建模型。
1、导入相关包
import numpy as np import re from nltk.corpus import stopwords stop = stopwords.words("english") from sklearn.feature_extraction.text import HashingVectorizer from sklearn.linear_model import SGDClassifier import pyprind
2、评论的预处理
#删除HTML标记和标点符号,去除停用词 def tokenizer(text): #去除HTML标记 text = re.sub("<[^>]*>","",text) #获取所有的表情符 emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text.lower()) #删除标点符号 text = re.sub("[\W]+"," ",text.lower())+" ".join(emoticons).replace("-","") #删除停用词 tokenized = [word for word in text.split() if word not in stop] return tokenized
3、读取电影评论
#读取文件,每次只读取一条记录 def stream_docs(path): with open(path,'r',encoding="utf-8") as csv: #去除列名 next(csv) for line in csv: #获取电影的评论和对应的情感标签 text,label = line[:-3],int(line[-2]) yield text,label #通过指定评论的条数来获取指定的评论 def get_minibatch(doc_stream,size): #初始化列表 docs,y = [],[] try: for _ in range(size): #获取电影的评论和标签 text,label = next(doc_stream) docs.append(text) y.append(label) except StopIteration: return None,None return docs,y
4、模型训练和预测
if __name__ == "__main__": #初始化特征向量对象,特征的数量为2^21 vect = HashingVectorizer(decode_error="ignore",n_features=2**21,preprocessor=None, tokenizer=tokenizer) clf = SGDClassifier(loss="log",random_state=1,n_iter=1) doc_stream = stream_docs("G:/dataset/move_data.csv") #初始化进度 pbar = pyprind.ProgBar(45) classes = np.array([0,1]) for _ in range(45): #每次获取1000条电影评论 train_x,train_y = get_minibatch(doc_stream,size=1000) if not train_x: break #将电影评论转成特征向量 train_x = vect.transform(train_x) #模型训练 clf.partial_fit(train_x,train_y,classes=classes) #更新进度条 pbar.update() #获取测试数据 test_x,test_y = get_minibatch(doc_stream,size=5000) test_x = vect.transform(test_x) #获取模型在训练集上的准确率 print("train Accuracy:%.3f"%clf.score(train_x,train_y)) #获取模型在训练集上的准确率 print("test Accuracy:%.3f"%clf.score(test_x,test_y)) #将测试集加入到模型中进行训练 clf = clf.partial_fit(test_x,test_y)
sklearn中的TfidfVectorizer在计算电影评论的特征向量时,需要将所有的电影评论加载到计算机的内存中来计算TF-IDF。sklearn还提供了HashingVectorizer来计算文本信息的向量,HashingVectorizer是独立数据,使用了32位的MurmurHash3算法。
总结:外存学习能提高训练模型的速度,但同时也会降低模型的准确率。在上一篇文章中,使用网格搜索和交叉验证获得的模型在训练集上的准确率为89.9%在测试集上的准确率为90.6%。所以在处理实际问题的时候,我们需要根据我们的需求来进行选择,从训练时间和资源消耗之间进行衡量。