Python基于机器学习的文本情感分析详细步骤[附代码和文字解释] 您所在的位置:网站首页 标签的制作过程怎么写 Python基于机器学习的文本情感分析详细步骤[附代码和文字解释]

Python基于机器学习的文本情感分析详细步骤[附代码和文字解释]

2024-07-07 19:32| 来源: 网络整理| 查看: 265

最近在研究情感分析,感谢CSDN上很多博主的文章,让我受益匪浅。因此在跑出准确率高达88%的分类结果后,写下自己的代码和总结,希望对大家有所帮助~

目录 一、文本数据预处理1、读取json并转化为列表2、文本清洗与处理1)去除网页链接2)判断字符串是否全是英文3)分词、识别英文单词、去除标点符号4)词性标注、词形还原、停用词过滤 3、处理数据集B完整代码及主函数4、处理数据集A的完整代码与主函数 二、训练算法模型1、文本特征表示2、训练算法模型1)随机划分数据集和训练集2)导入算法模型3)训练算法模型4)预测测试集中的文本情感5)评估分类效果 3、保存及调用训练好的算法模型1)保存训练好的模型2)调用之前保存的模型 4、词袋模型和贝叶斯模型串联的完整代码5、TF-IDF和支持向量机串联预测的完整代码

一、文本数据预处理

情感分析主要涉及两个数据集,一个是人工标注好的数据集,即包含了情感标签和文本的数据集A,另一个是用于情感分析的原始数据集,即只包含文本的数据集B。数据集A用于训练和测试,数据集B用于得到想要的情感分析结果。

本文数据集A为斯坦福大学的Sentiment140数据集,包含了160万条标注情感极性的推文。数据集B为我从TwitterAPI上爬取的两个月推文。

预处理主要是处理数据集B中的原始数据和数据集A中的文本,目的是将包含网页链接、标点符号及无意义单词的杂乱数据转化为干净的由有意义单词组成的字符串,并使用pandas dataframe存储。

1、读取json并转化为列表

初始爬取到的推文为json格式,因此需要读取json文件,并将其中的每条推文存储到列表中,目标格式为 [‘今天天气真好’,‘This is my bag’]

import json def get_tweets(filepath): tweets = [] file = open(filepath, 'r') for line in file.readlines():#由于json为多层嵌套,所以分行读取 dic = json.loads(line) #将json转化为字典 text = str(dic.get('text', '!')) #如果字典中'text'键为空,则返回'!',不处理会返回None tweets.append(text) return tweets 2、文本清洗与处理 1)去除网页链接

使用正则表达式去除http,https网页链接

import re def remove_urls(vTEXT): vTEXT = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '', vTEXT, flags=re.MULTILINE) return (vTEXT) 2)判断字符串是否全是英文

使用ASCII字符串的取值范围判断是否是英文字符串

def judge_english(text): return all(ord(c) 2] #判断是否是长度大于2的英文单词并转化为小写字母 return words 4)词性标注、词形还原、停用词过滤 相较于词干提取,词形还原的结果更具有可读性,词干提取把词的后缀删减掉,比如luckily缩减为lucki,而lucki并不是单词,词形还原则是将ate还原为eat,将luckily还原为lucky,还原结果仍是英文单词。词形还原依赖于对词性进行准确的标注,不进行标注的话函数默认词性为名词进行还原,还原结果并不好,如wnl.lemmatize(‘ate’)结果仍是‘ate’,标注动词词性后wnl.lemmatize(‘ate’,‘V’)还原为‘eat’停用词过滤使用nltk的英文停用词词典 from nltk.corpus import stopwords from nltk.stem import WordNetLemmatizer from nltk import pos_tag from nltk.corpus import wordnet stoplist = set(stopwords.words('english'))#停用词词典 def get_pos_word(words): # def get_wordnet_pos(tag): if tag.startswith('J'): return wordnet.ADJ elif tag.startswith('V'): return wordnet.VERB elif tag.startswith('N'): return wordnet.NOUN elif tag.startswith('R'): return wordnet.ADV else: return None words = pos_tag(words) #词性标注 pos_word = [wnl.lemmatize(tag[0], pos=get_wordnet_pos(tag[1]) or wordnet.NOUN) for tag in words] #词形还原 # 停用词过滤 cleanwords = [word for word in pos_word if word not in stoplist] return cleanwords 3、处理数据集B完整代码及主函数

使用pandas dataframe存储处理后的文本数据并保存为csv格式文件

import json import re import enchant from nltk.corpus import stopwords from nltk.stem import WordNetLemmatizer import pandas as pd from nltk import pos_tag from nltk.corpus import wordnet from nltk.tokenize import TweetTokenizer wnl = WordNetLemmatizer() USdict = enchant.Dict("en_US") stoplist = set(stopwords.words('english')) # 获取处理后的英文推特 def get_tweets(filepath): tweets = [] file = open(filepath, 'r') # 去除链接 def remove_urls(vTEXT): vTEXT = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '', vTEXT, flags=re.MULTILINE) return (vTEXT) # 筛选英文 def judge_english(text): return all(ord(c) 2] return words # 词性还原 def get_pos_word(words): def get_wordnet_pos(tag): if tag.startswith('J'): return wordnet.ADJ elif tag.startswith('V'): return wordnet.VERB elif tag.startswith('N'): return wordnet.NOUN elif tag.startswith('R'): return wordnet.ADV else: return None words = pos_tag(words) pos_word = [wnl.lemmatize(tag[0], pos=get_wordnet_pos(tag[1]) or wordnet.NOUN) for tag in words] # 停用词过滤 cleanwords = [word for word in pos_word if word not in stoplist] return cleanwords if __name__ == '__main__': filepath='D:/data/test.json' storename = 'D:/data/test.csv' tweets = get_tweets(filepath) df = pd.DataFrame() df['tweets'] = tweets # 分词 df['tweets'] = df['tweets'].apply(get_word) # 词形还原 df['tweets'] = df['tweets'].apply(get_pos_word) # 删除tweets中的空列表 df = df[~(df['tweets'].str.len() == 0)] # 将列表转换为字符串 df['tweets'] = df['tweets'].apply(lambda x: ' '.join(x)) # 保存文本 df.to_csv(storename, encoding='utf-8') 4、处理数据集A的完整代码与主函数

不同于处理数据集B,数据集A为行列数据整齐的英文文本,但是没有列名,且有几列多余数据,因此主要加入了对csv格式文件的读取和处理,注意本文使用的数据集A编码格式为 ISO-8859-1,大家读取csv文件 读取csv文件 encoding=‘ISO-8859-1’ 报错时改成 encoding=‘utf-8’

import enchant from nltk.corpus import stopwords from nltk.stem import WordNetLemmatizer from nltk import pos_tag from nltk.corpus import wordnet from nltk.tokenize import TweetTokenizer import pandas as pd import re wnl = WordNetLemmatizer() USdict = enchant.Dict("en_US") stoplist = set(stopwords.words('english')) def remove_urls(vTEXT): vTEXT = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '', vTEXT, flags=re.MULTILINE) return (vTEXT) def get_word(text): text = text.replace('.', ' ') tknzr = TweetTokenizer(strip_handles=True, reduce_len=True) rawwords = tknzr.tokenize(text) words = [word.lower() for word in rawwords if USdict.check(word) and not str.isdigit(word) and len(word) > 2] return words def get_pos_word(words): def get_wordnet_pos(tag): if tag.startswith('J'): return wordnet.ADJ elif tag.startswith('V'): return wordnet.VERB elif tag.startswith('N'): return wordnet.NOUN elif tag.startswith('R'): return wordnet.ADV else: return None words = pos_tag(words) pos_word = [wnl.lemmatize(tag[0], pos=get_wordnet_pos(tag[1]) or wordnet.NOUN) for tag in words] # 停用词过滤 cleanwords = [word for word in pos_word if word not in stoplist] return cleanwords if __name__ == '__main__': file = pd.read_csv('D:/data/Train.csv', encoding='ISO-8859-1', header=None, names=['label', 'id', 'day', 'query', 'user', 'tweets']) #pandas dataframe自定义列表名 file = file.drop(file.columns[1:5], axis=1) #删除多余列 #去除链接 df['tweets'] = df['tweets'].apply(remove_urls) # 分词 df['tweets'] = df['tweets'].apply(get_word) # 文本处理结果 df['tweets'] = df['tweets'].apply(get_pos_word) # 删除tweets中的空列表 df = df[~(df['tweets'].str.len() == 0)] # 转换字符串 df['tweets'] = df['tweets'].apply(lambda x: ' '.join(x)) # 打乱顺序 df = df.sample(frac=1.0).reset_index(drop=True) #保存文本 df.to_csv("D:\data\Test5000.csv", encoding='utf-8',index=None) 二、训练算法模型

本文主要使用sklearn中封装的模型进行训练

1、文本特征表示

分别使用词袋模型和TF-IDF进行文本特征表示,max_features参数是指选取的特征数最大值,大家根据各自的数据情况和需要制定最大值

from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfVectorizer #词袋模型 bow_vectorizer = CountVectorizer(max_df=0.80, min_df=2, max_features=5000) # TF-IDF feature tfidf_vectorizer = TfidfVectorizer(max_df=0.80, min_df=2, max_features=5000) 2、训练算法模型 1)随机划分数据集和训练集

将数据集A中人工标注的标签和文本分别作为因变量y和自变量x,并使用sklearn中的train_test_split进行随机划分,test_size参数为测试集比例,一般选择0.2,即80%训练集,20%测试集

from sklearn.model_selection import train_test_split df = pd.read_csv("D:\data\Train.csv", encoding='utf-8') x=df['tweets'] #自变量 y=df['label'] #因变量 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1) #划分测试集和训练集 2)导入算法模型

本文选取五种算法模型:K近邻、逻辑回归、随机森林、支持向量机、朴素贝叶斯进行模型训练

from sklearn.linear_model import LogisticRegression from sklearn.naive_bayes import MultinomialNB from sklearn.linear_model import SGDClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.ensemble import RandomForestClassifier # KNN Classifier K近邻算法 Knn = KNeighborsClassifier() # Logistic Regression Classifier 逻辑回归 Lr = LogisticRegression() # Random Forest Classifier 随机森林 Rf = RandomForestClassifier() # SVM Classifier 支持向量机 Svm = SGDClassifier() # Naive Bayes 朴素贝叶斯 Nb = MultinomialNB() 3)训练算法模型

为了防止出错和精简代码,本文使用pipe管道封装文本特征表示和算法模型两个步骤,后续直接使用pipe拟合即可,这里以串联词袋模型和朴素贝叶斯为例,也可以串联词袋模型和随机森林等等,根据需要串联即可。

from sklearn.pipeline import make_pipeline pipe = make_pipeline(bow_vectorizer, Nb) #词袋模型串联朴素贝叶斯算法 pipe.fit(x_train, y_train) 4)预测测试集中的文本情感 y_pred = pipe.predict(x_test) #进行预测 df['pred']=y_pred #将预测结果保存到dataframe中 5)评估分类效果

常用的分类算法评估指标包括:准确率(Accuracy)、精准度(Precision)、召回率(Recall)和F1值(F1-score),使用sklearn自带的metrics即可得到包含上面几个指标的分类效果评估报告。

from sklearn import metrics print(metrics.classification_report(y_test, y_pred)) 3、保存及调用训练好的算法模型 1)保存训练好的模型

为了防止以后每次进行数据时都要进行拟合,直接使用sklearn自带的joblib即可保存训练好的模型。

from sklearn.externals import joblib joblib.dump(pipe, 'D:/data/Bayes.pkl') 2)调用之前保存的模型 Bayes=joblib.load('D:/data/Bayes.pkl') #加载模型 y_pred = Bayes.predict(x_test) #预测结果和pipe一致 df['pred02']=y_pred #将预测结果保存到dataframe中 4、词袋模型和贝叶斯模型串联的完整代码 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import CountVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn.pipeline import make_pipeline from sklearn.externals import joblib df = pd.read_csv("D:\data\Train.csv", encoding='utf-8') df = df.sample(frac=1.0).reset_index(drop=True) x=df['tweets'] #自变量 y=df['label'] #因变量 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1) #划分测试集和训练集 # 词袋模型 bow_vectorizer = CountVectorizer(max_df=0.80, min_df=2) #贝叶斯模型 Nb = MultinomialNB() pipe = make_pipeline(bow_vectorizer, Nb) pipe.fit(x_train, y_train) y_pred = pipe.predict(x_test) #预测 df['pred']=y_pred #保存预测结果到dataframe中 print(metrics.classification_report(y_test, y_pred)) #评估 joblib.dump(pipe, 'D:/data/Bayes.pkl') #保存模型 5、TF-IDF和支持向量机串联预测的完整代码 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import SGDClassifier from sklearn.pipeline import make_pipeline from sklearn.externals import joblib df = pd.read_csv("D:\data\Train.csv", encoding='utf-8') df = df.sample(frac=1.0).reset_index(drop=True) x=df['tweets'] #自变量 y=df['label'] #因变量 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1) #划分测试集和训练集 # TF-IDF tfidf_vectorizer = TfidfVectorizer(max_df=0.80, min_df=2) # SVM Classifier Svm = SGDClassifier() pipe = make_pipeline(tfidf_vectorizer, Svm) pipe.fit(x_train, y_train) y_pred = pipe.predict(x_test) #预测 df['pred']=y_pred #保存预测结果到dataframe中 print(metrics.classification_report(y_test, y_pred)) #评估 joblib.dump(pipe, 'D:/data/SVM.pkl') #保存模型


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有