在线算法外存学习处理大数据集

时间:2022-01-29 13:09:55

在上一篇文章中,使用了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%。所以在处理实际问题的时候,我们需要根据我们的需求来进行选择,从训练时间和资源消耗之间进行衡量。