博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python3基于 Doc2Vec 的电影评论分析实战
阅读量:4287 次
发布时间:2019-05-27

本文共 5107 字,大约阅读时间需要 17 分钟。

环境描述:

       python环境:python3.6

需求描述:

       本文使用IMDB 电影评论数据集作为示例来测试 Doc2Vec 在情感分析中的有效性,数据集中包含了 5,000 条积极评论,5,000 条消极评论和 5,000 条未标记的电影评论。我们首先利用 Doc2Vec 对未标记评论进行训练。除了同时使用 DM 和 DBOW 向量作为输入以外,对积极和消极情绪的评论进行了随机采样,并按80 / 20 的比例分为了训练集/ 测试集。我们会用到 Scikit-Learn 这个第三方库做大量的机器学习

参考博客地址:

       对于参考博客的一些实现细节已经存在bug,所以本文将优化后的代码贴出来分享给读者

关于提升精度的一些建议:

       1.本文中作者使用的训练循环字数为3,原文作者使用的是10,如果读者的电脑性能够高,可以修改该训练参数,精度应该可以接近论文的理论值

       2.本文作者使用的训练向量的维度为300,可以参照论文使用500(应该会有小幅提升)

       3.增加训练的文本数量,本文使用的训练的文本为各个类型5000行,如果电脑配置够高可以适量增加,作者尝试多次使用理论的测试样本文本训练,没有一次成功(可能原因是电脑配置确实普通,二可能是超出了训练的最大量),期待读者能全量训练测试看看

        代码已放在git上,欢迎优化及分享相关技术:

        备注:训练样本放在工程下,可以自取

代码实例:

#-*- coding: utf-8 -*-from sklearn.model_selection import train_test_splitimport numpy as npimport osimport gensimimport randomimport datetimefrom sklearn.metrics import roc_curve, aucimport matplotlib.pyplot as pltfrom sklearn.linear_model import SGDClassifierLabeledSentence = gensim.models.doc2vec.LabeledSentencepath = os.getcwd()size = 300start = datetime.datetime.now()with open(path[:-9] + '\\aclImdb\\train\\pos_all3.txt', 'r', encoding="utf-8") as infile:    pos_tweets = infile.readlines()with open(path[:-9] + '\\aclImdb\\train\\neg_all3.txt', 'r', encoding="utf-8") as infile:    neg_tweets = infile.readlines()with open(path[:-9] + '\\aclImdb\\train\\unsup_all3.txt', 'r', encoding="utf-8") as infile:    unsup_reviews = infile.readlines()# 1 代表积极情绪,0 代表消极情绪y = np.concatenate((np.ones(len(pos_tweets)), np.zeros(len(neg_tweets))))x_train, x_test, y_train, y_test = train_test_split(np.concatenate((pos_tweets, neg_tweets)), y, test_size=0.2)# 零星的预处理def cleanText(corpus):    punctuation = """.,?!:;(){}[]"""    corpus = [z.lower().replace('n', '') for z in corpus]    corpus = [z.replace('<br />', ' ') for z in corpus]    # 将标点视为一个单词    for c in punctuation:        corpus = [z.replace(c, ' %s ' % c) for z in corpus]    corpus = [z.split() for z in corpus]    return corpusprint("start clean Text")x_train = cleanText(x_train)x_test = cleanText(x_test)unsup_reviews = cleanText(unsup_reviews)print("end clean text")# Gensim 的 Doc2Vec 工具要求每个文档/段落包含一个与之关联的标签。我们利用 LabeledSentence 进行处理。# 格式形如 “TRAIN_i” 或者 “TEST_i”,其中 “i” 是假的评论索引。def labelizeReviews(reviews, label_type):    labelized = []    for i, v in enumerate(reviews):        label = '%s_%s' % (label_type, i)        labelized.append(LabeledSentence(v, [label]))    return labelizedprint("start labelize")x_train = labelizeReviews(x_train, 'TRAIN')x_test = labelizeReviews(x_test, 'TEST')unsup_reviews = labelizeReviews(unsup_reviews, 'UNSUP')# 实例化 DM 和 DBOW 模型model_dm = gensim.models.Doc2Vec(min_count=1, window=10, size=size, sample=1e-3, negative=5, workers=3)model_dbow = gensim.models.Doc2Vec(min_count=1, window=10, size=size, sample=1e-3, negative=5, dm=0, workers=3)a = []a.extend(x_train)a.extend(x_test)a.extend(unsup_reviews)print("before build")# 对所有评论创建词汇表model_dm.build_vocab(a)model_dbow.build_vocab(a)print("end build vocab")# 多次传入数据集,通过每次滑动(shuffling)来提高准确率。all_train_reviews = np.concatenate((x_train, unsup_reviews))b =[]b.extend(x_train)b.extend(unsup_reviews)def sentences_perm(sentences):    shuffled = list(sentences)    random.shuffle(shuffled)    return (shuffled)print("before train")for epoch in range(3):    model_dm.train(sentences_perm(b), total_examples=model_dm.corpus_count, epochs=1)    print("train one end")    model_dbow.train(sentences_perm(b), total_examples=model_dbow.corpus_count, epochs=1)print("end all train")# 从我们的模型中获得训练过的向量def getVecs(model, corpus, size):    vecs = [np.array(model[z.tags[0]]).reshape((1, size)) for z in corpus]    return np.concatenate(vecs)print("before get vecs")train_vecs_dm = getVecs(model_dm, x_train, size)train_vecs_dbow = getVecs(model_dbow, x_train, size)train_vecs = np.hstack((train_vecs_dm, train_vecs_dbow))print("end get vecs")# 训练测试数据集c = []c.extend(x_test)print("before last train")for epoch in range(3):    model_dm.train(sentences_perm(c), total_examples=model_dm.corpus_count,epochs=1)    print("train two end")    model_dbow.train(sentences_perm(c), total_examples=model_dbow.corpus_count,epochs=1)print("end last train")# 创建测试数据集向量test_vecs_dm = getVecs(model_dm, x_test, size)test_vecs_dbow = getVecs(model_dbow, x_test, size)test_vecs = np.hstack((test_vecs_dm, test_vecs_dbow))print("end get last vecs")print("start show")lr = SGDClassifier(loss='log', penalty='l1')lr.fit(train_vecs, y_train)print('Test Accuracy: %.2f' % lr.score(test_vecs, y_test))end = datetime.datetime.now()print("运行时长:")print(end - start)pred_probas = lr.predict_proba(test_vecs)[:, 1]fpr, tpr, _ = roc_curve(y_test, pred_probas)roc_auc = auc(fpr, tpr)plt.plot(fpr, tpr, label='area = %.2f' % roc_auc)plt.plot([0, 1], [0, 1], 'k--')plt.xlim([0.0, 1.0])plt.ylim([0.0, 1.05])plt.legend(loc='lower right')plt.show()

 

执行日志:

python3 train_text3.py

start clean Text
end clean text
start labelize
before build
end build vocab
before train
train one end
train one end
train one end
end all train
before get vecs
end get vecs
before last train
train two end
train two end
train two end
end last train
end get last vecs
start show
Test Accuracy: 0.79
运行时长:
3:06:39.693985

截图:

亲,点个赞再走吧,感谢您的鼓励

 

转载地址:http://rzagi.baihongyu.com/

你可能感兴趣的文章
【HttpClient4.5中文教程】五. HttpClient执行上下文HttpContext
查看>>
【Mybatis3学习入门】【一】从JDBC到Mybatis
查看>>
【Mybatis3学习入门】【二】Mybatis快速入门
查看>>
JDBC进化史--从JDBC1.0到JDBC4.2
查看>>
XML-DOM&SAX解析
查看>>
XML-使用XStream
查看>>
XML-JDOM和DOM4J比较
查看>>
Java与Json
查看>>
Javaweb的web.xml中<url-pattern>配置
查看>>
HTTPS推荐文章
查看>>
【HttpClient4.5中文教程】六. HTTP协议拦截器
查看>>
【HttpClient4.5中文教程】七. 异常处理
查看>>
【HttpClient4.5中文教程】八.终止请求和重定向处理
查看>>
数字证书原理
查看>>
Java中使用JSSE实现SSL/TLS安全协议
查看>>
数字证书原理(1)
查看>>
java泛型简介
查看>>
java后端程序员书单
查看>>
系列文章--HTML5学习系列链接
查看>>
AngularJS 单选多选简介
查看>>