Python基于机器学习的⽂本情感分析详细步骤[附代码和⽂字解释]
最近在研究情感分析,感谢CSDN上很多博主的⽂章,让我受益匪浅。因此在跑出准确率⾼达88%的分类结果后,写下⾃⼰的代码和总结,希望对⼤家有所帮助~
⽬录
⼀、⽂本数据预处理
情感分析主要涉及两个数据集,⼀个是⼈⼯标注好的数据集,即包含了情感标签和⽂本的数据集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 adlines():#由于json为多层嵌套,所以分⾏读取
dic = json.loads(line)#将json转化为字典
text =('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)<128for c in text)#包括英⽂⽂本、英⽂标点符号
3)分词、识别英⽂单词、去除标点符号
这⾥使⽤nltk的TweetTokenizer进⾏英⽂分词,strip_handles参数表⽰删除句柄,即@Justin这种格式的短语,如果没有删除句柄的需求可以使⽤nltk的tokenize,将字符串分词为列表
使⽤enchant检查字符串是否是英⽂单词,这是⽐nltk更全⾯的英⽂词典库,但是enchant将 They’re 这种缩略词也判定为英⽂单词,因此使⽤ isalpha() 函数加⼀层过滤,筛选掉含有标点符号的字符串,只保留纯英⽂字符串
import enchant
kenize import TweetTokenizer
def get_word(text):
USdict = enchant.Dict("en_US")#英语词典
text = place('.',' ')#将句号替换为空格
tknzr = TweetTokenizer(strip_handles=True, reduce_len=True)#删除句柄
rawwords = kenize(text)#分词
words =[word.lower()for word in rawwords if USdict.check(word)and word.isalpha()and len(word)>2]#判断是否是长度⼤于2的英⽂单词并转化为⼩写字母
return words
4)词性标注、词形还原、停⽤词过滤
相较于词⼲提取,词形还原的结果更具有可读性,词⼲提取把词的后缀删减掉,⽐如luckily缩减为lucki,⽽lucki并不是单词,词形还原则是将ate还原为eat,将luckily还原为lucky,还原结果仍是英⽂单词。
词形还原依赖于对词性进⾏准确的标注,不进⾏标注的话函数默认词性为名词进⾏还原,还原结果并不好,如wnl.lemmatize(‘ate’)结果仍是‘ate’,标注动词词性后wnl.lemmatize(‘ate’,‘V’)还原为‘eat’
停⽤词过滤使⽤nltk的英⽂停⽤词词典
pus import stopwords
from nltk.stem import WordNetLemmatizer
from nltk import pos_tag
pus 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)#词性标注python怎么读取json文件
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 re
import enchant
pus import stopwords
from nltk.stem import WordNetLemmatizer
import pandas as pd
from nltk import pos_tag
pus import wordnet
kenize 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)<128for c in text)
# 获取⽂本
for line adlines():
dic = json.loads(line)
text =('text','!'))
if judge_english(text):
tweets.append(remove_urls(text))
return tweets
def get_word(text):
text = place('.',' ')
tknzr = TweetTokenizer(strip_handles=True, reduce_len=True)
rawwords = kenize(text)
words =[word.lower()for word in rawwords if USdict.check(word)and word.isalpha()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__':
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))
# 保存⽂本
<_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
pus import stopwords
from nltk.stem import WordNetLemmatizer
from nltk import pos_tag
pus import wordnet
kenize 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 = place('.',' ')
tknzr = TweetTokenizer(strip_handles=True, reduce_len=True)
rawwords = kenize(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:
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.lumns[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)
#保存⽂本
<_csv("D:\data\Test5000.csv", encoding='utf-8',index=None)
⼆、训练算法模型
本⽂主要使⽤sklearn中封装的模型进⾏训练
1、⽂本特征表⽰
分别使⽤词袋模型和TF-IDF进⾏⽂本特征表⽰,max_features参数是指选取的特征数最⼤值,⼤家根据各⾃的数据情况和需要制定最⼤值
from sklearn. import CountVectorizer
from sklearn. 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%测试集

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。