【人工智能项目】- 卷积神经网络实现游客评价情绪鉴别

【人工智能项目】- 卷积神经网络实现游客评价情绪鉴别

本次主要任务是对游客发表的评价内容的情绪进行鉴别,积极还是消极。

读取数据

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os

plt.rcParams['font.family'] = "SimHei"
plt.rcParams['axes.unicode_minus'] = "False"
plt.rcParams['font.size'] = 15

data = pd.read_csv('data.csv')
data
Unnamed: 0contentsentiment
00第一天,去了土楼,路上车程比较长,我自己带了个小枕头,让脖子舒服点,还有建议大家穿比较合脚的...
11导游王艺芳带的很好,我们很慢,总是让他操心,但他很负责。耐心详细介绍带领😊经历了好多风景… ...
22整个行程轻松自由。第一天在中山路步行街,有很多厦门小吃和海鲜店,土笋冻、 海蛎煎、五香卷,很...
33第一天早点到这 可以骑小黄车或者坐地铁去中山路玩一圈(奢侈品和各种小吃)。第二天去土楼。第二...
44这个冬天,我路过了厦门的满树繁花、万家灯火和四海长风。厦门,是一座骨子里透着浪漫与精致的城市...
............
39953995同程真是越来越**,说好的看到海,结果根本看不到,不如自己去定
39963996硬件还行,软件**。寄个快递礼品盒全压坏!硬塞的能再恶心点?!!!真****
39973997非常差的一次服务,因为和产品经理熟了所以愿意相信他。对他的服务非常满意。对此次三亚地接导游非...
39983998不满意
39993999导游蔡文佳非常不错,很热情,必须赞!最不满意就是酒店,我住的是阳光大酒店,说是五星级,进去一...

4000 rows × 3 columns

数据EDA

# 查看数据的NAN情况
#data.info()
data.isnull().sum()
Unnamed: 0    0
content       0
sentiment     0
dtype: int64
# 去除多余索引列
data = data.drop(labels='Unnamed: 0',axis=1)
data
contentsentiment
0第一天,去了土楼,路上车程比较长,我自己带了个小枕头,让脖子舒服点,还有建议大家穿比较合脚的...
1导游王艺芳带的很好,我们很慢,总是让他操心,但他很负责。耐心详细介绍带领😊经历了好多风景… ...
2整个行程轻松自由。第一天在中山路步行街,有很多厦门小吃和海鲜店,土笋冻、 海蛎煎、五香卷,很...
3第一天早点到这 可以骑小黄车或者坐地铁去中山路玩一圈(奢侈品和各种小吃)。第二天去土楼。第二...
4这个冬天,我路过了厦门的满树繁花、万家灯火和四海长风。厦门,是一座骨子里透着浪漫与精致的城市...
.........
3995同程真是越来越**,说好的看到海,结果根本看不到,不如自己去定
3996硬件还行,软件**。寄个快递礼品盒全压坏!硬塞的能再恶心点?!!!真****
3997非常差的一次服务,因为和产品经理熟了所以愿意相信他。对他的服务非常满意。对此次三亚地接导游非...
3998不满意
3999导游蔡文佳非常不错,很热情,必须赞!最不满意就是酒店,我住的是阳光大酒店,说是五星级,进去一...

4000 rows × 2 columns

数据清洗

data.drop_duplicates(inplace=True)#查找重复值并删除
print(data.duplicated().sum())
0
import re#文本内容清洗
import string
def remove_punctuation(s):
#     print(s)
    delEStr = string.punctuation + ''+ string.digits + string.ascii_letters# 标点符号、数字、字母
    identify = str.maketrans(","," ",delEStr)# 这里感觉并没有用到映射的功能,而是着重使用到了 删除指定字符串 的功能
    s = s.translate(identify)
#     print(s,type(s))
    s = re.sub(r"[!\"#$%&'()*+,-./:;<=>?@[\\\]¯~_`{|}~·—!,。?、¥…():;【】《》‘’“”\s]+",'',s) # 正则匹配并替换
    return s

data['content'] = data['content'].apply(remove_punctuation)
data.sample(5)
#data["content"].count()
contentsentiment
2249第一次自由行出发前还很忐忑怕安排的不好结果客服的服务很到位有什么问题问她立马就给我电话回复过...
3760导游凶神恶煞一脸恶相吐个槽要被他两小时
773这次出行总体还不错出发前一天我的专属客服帮忙定的行程很专业人也很好由于是不同旅行套餐的人组团...
3142去的时候飞机整整延误了三个多小时好心情都给破坏了还好泛太平洋酒店还不错第二天孩子在他们的露天...
3772服务很差的回程最后一天遇到台风是航空公司先打电话给我的然后打电话给同程时候她们都不知道航班取...
# print(string.punctuation)
for i in data.iloc[:,0]:
    clean_data = remove_punctuation(i)
    print(clean_data)
#     break
第一天去了土楼路上车程比较长我自己带了个小枕头让脖子舒服点还有建议大家穿比较合脚的运动鞋因为土楼的路高低不平坑坑洼洼容易脚疼一定要穿上舒服的鞋子这点很重要鼓浪屿的路虽然不会像土楼那样但是上坡下坡很多走的比较辛苦所以不需要的东西不要带轻松上岛龙头路的美食很多但是卫生很重要一定要选择干净卫生的店海鲜也比较多价格也不贵喜欢吃海鲜的有口福了厦大开放时间有规定不过我们的导游林珊珊安排的很合理在厦大开放前先带我们去了南普陀参观讲解的很详细听的津津有味然后让我们自由活动去参观厦前的提醒服务非常被动滞后


通过同程旅游纪天宇订的厦门日自由行第一次通过同程跑远地方旅游感觉各方面都是非常满意唯一一点遗憾就是春秋航空去厦门那天晚点个小时还好意外险有买不知道有没有理赔酒店住的泛太平洋星酒店含日双人早饭酒店服务相当满意行程方面第一天因为飞机延误直接入住酒店睡觉第二天满满的行程都是坐的公交车先中山路步行街看看厦门特产东西有些贵–厦门大学就
import jieba 
def cut_word(text):
    return jieba.cut(text)
data['content']=data['content'].apply(cut_word)
data.sample(5)
contentsentiment
2912<generator object Tokenizer.cut at 0x000001F67...
2219<generator object Tokenizer.cut at 0x000001F67...
2640<generator object Tokenizer.cut at 0x000001F67...
37<generator object Tokenizer.cut at 0x000001F67...
3593<generator object Tokenizer.cut at 0x000001F67...
def get_stopword():
    s = set()
    with open('stop_words.txt','r',encoding='utf-8') as f:
        for line in f:
            s.add(line.strip())
    return s 

def remove_stopword(words):
    return [word for word in words if word not in stopword]

stopword = get_stopword()
data['content'] = data['content'].apply(remove_stopword)
data.sample(5)
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\LVCHAO~1\AppData\Local\Temp\jieba.cache
Loading model cost 0.896 seconds.
Prefix dict has been built successfully.
contentsentiment
2677[这次, 预定, 自由, 行, 产品, 全程, 入住, 厦门, 泛太平洋, 大酒店, 地处,...
2248[第二次, 同程, 出游, 服务, 一如既往, 好, 此次, 厦门, 选择, 自由, 行在,...
3264[这次, 买, 机票, 过去, 住宿, 餐饮, 认为, 厦门, 不好玩, 接送, 服务]
3436[厦门, 旅游, 热, 走路, 两分钟, 流汗, 两, 小时, 捕蟹, 只, 半小时, 受不...
2482[住, 好, 唯一, 航班, 太, 不靠, 谱, 加钱, 机票, 划不来, 下午, 飞机, ...
t = data['sentiment'].value_counts()
print(t)
t.plot(kind="bar")
正    2852
负     507
中     455
Name: sentiment, dtype: int64

在这里插入图片描述

data["content"]
0       [第一天, 土楼, 路上, 车程, 比较, 长, 小, 枕头, 脖子, 舒服, 点, 建议,...
1       [导游, 王艺芳, 好, 慢, 总是, 操心, 负责, 耐心, 详细, 介绍, 带领, 😊,...
2       [整个, 行程, 轻松自由, 第一天, 中山路, 步行街, 厦门, 小吃, 海鲜店, 土笋,...
3       [第一天, 早点, 骑小, 黄车, 坐地铁, 中山路, 玩, 一圈, 奢侈品, 小吃, 第二...
4       [冬天, 路过, 厦门, 满树, 繁花, 万家灯火, 四海, 长风, 厦门, 一座, 骨子里...
                              ...                        
3994    [这次, 旅程, 真的, 太, 失望, 要求, 大床, 房, 变成, 标准间, 导游, 不负...
3995                [同程, 真是, 越来越, 说好, 看到, 海, 根本, 看不到, 去定]
3996       [硬件, 行, 软件, 寄个, 快递, 礼品盒, 全, 压坏, 硬塞, 再, 恶心, 点真]
3997    [差, 一次, 服务, 产品, 经理, 熟, 愿意, 相信, 服务, 满意, 此次, 三亚,...
3999    [导游, 蔡文佳, 不错, 热情, 赞, 最, 满意, 酒店, 住, 阳光, 大酒店, 说,...
Name: content, Length: 3814, dtype: object
from itertools import chain
from collections import Counter

li_2d = data['content'].tolist()
li_1d = list(chain.from_iterable(li_2d))
#二位列表转换为一维列表
print(f'总词汇量:{len(li_1d)}')
c = Counter(li_1d)
print(f'不重复词汇量:{len(c)}')
common = c.most_common(15)
print(common)

      
总词汇量:172537
不重复词汇量:16695
[('酒店', 4271), ('好', 2843), ('厦门', 2344), ('不错', 2135), ('同程', 1895), ('鼓浪屿', 1656), ('导游', 1649), ('服务', 1564), ('行程', 1446), ('说', 1322), ('安排', 1161), ('吃', 961), ('住', 909), ('这次', 889), ('比较', 880)]
d = dict(common)
plt.figure(figsize=(15,5))
plt.bar(d.keys(),d.values())

在这里插入图片描述

total = len(li_1d)
percentage = [v*100/total for v in d.values()]
plt.figure(figsize=(15,5))
plt.bar(d.keys(),percentage)

在这里插入图片描述

from wordcloud import WordCloud#词云
from PIL import Image
#wc = WordCloud(font_path=r'C:\Users\dell\Desktop\旅游\font.ttf',width=600,height=400)
#bg = WordCloud(mask = plt.imread(r'C:\Users\dell\Desktop\旅游\bgf.jpg'))
img = Image.open(r'123.jpg') # 打开背景图片
img_array = np.array(img) # 将图片转换为数组
wc = WordCloud(
    background_color="black", # 将背景颜色设置为黑色,也可根据个人喜好更改
    mask=img_array,#背景图
    max_words=100,
    font_path = r"font.ttf", #字体设置
    width=1000).generate_from_frequencies(c)
plt.imshow(wc)
plt.axis('off')
wc.to_file("pic.png")

在这里插入图片描述

#构建训练与测试集
def join(text_list):
    return " ".join(text_list)

data["content"] = data["content"].apply(join)
data.sample(5)
contentsentiment
468总体 满分 导游 人 好
490林珊珊 美女 导游
1466厦门 自由 行 安排 不错 鼓浪屿 风景 好 旅游社 服务 下次 出行 一定 找 贵
3792飞机 晚点 小时 酒店 服务 不错 酒店 硬件 不行 酒店 私有 海滩 公共 沙滩
125好 尤其 最后 一天 导游 小张 张立 导游 细心 专业
#标签列转换为离散值
data["sentiment"] = data["sentiment"].map({"正":0,"中":1,"负":2})
data["sentiment"].value_counts()
0    2852
2     507
1     455
Name: sentiment, dtype: int64
data
contentsentiment
0第一天 土楼 路上 车程 比较 长 小 枕头 脖子 舒服 点 建议 穿 比较 合脚 运动鞋 ...0
1导游 王艺芳 好 慢 总是 操心 负责 耐心 详细 介绍 带领 😊 经历 好多 风景 海边 ...0
2整个 行程 轻松自由 第一天 中山路 步行街 厦门 小吃 海鲜店 土笋 冻 海蛎 煎 五香 ...0
3第一天 早点 骑小 黄车 坐地铁 中山路 玩 一圈 奢侈品 小吃 第二天 土楼 第二天 庄常...0
4冬天 路过 厦门 满树 繁花 万家灯火 四海 长风 厦门 一座 骨子里 透着 浪漫 精致 城...0
.........
3994这次 旅程 真的 太 失望 要求 大床 房 变成 标准间 导游 不负责任 尽到 应 义务 导...2
3995同程 真是 越来越 说好 看到 海 根本 看不到 去定2
3996硬件 行 软件 寄个 快递 礼品盒 全 压坏 硬塞 再 恶心 点真2
3997差 一次 服务 产品 经理 熟 愿意 相信 服务 满意 此次 三亚 地接 导游 一味 说 金...2
3999导游 蔡文佳 不错 热情 赞 最 满意 酒店 住 阳光 大酒店 说 五星级 一看 旅店 舒服...2

3814 rows × 2 columns

对数据打乱顺序并保存好训练和测试数据

# 打乱顺序
data  = data.sample(frac=1).reset_index(drop=True)
data
contentsentiment
0年前 老公 夏威夷 选择 同程 这次 国内游 满意 厦门 当地 导游 比较 热情 接机 准时...0
1想 如实 写出 感受 第一天 自由 行 晚上 六点 第二天 云水 谣 领队 郑 导游 联系 ...2
2厦门 这次 游玩 满意 游玩 开心 安排 星 酒店 不错 住 舒适 出门 公交 出行 方便 ...0
3这次 自由 行 比较满意 住 五星级 酒店 泛太平洋 地理位置 不错 市区 这次 坐 动车 ...0
4买 经停 飞机 商量 信誉 大打折扣2
.........
3809出游 安排 合理 导游 服务 棒棒 哒0
3810鼓浪屿 导游 服务 好0
3811玩 开心 好评0
3812回来 航班 延误 小时 机上 空乘 个个 帅哥 哈哈哈哈 第二次 厦门 总体 不错 八市 海...0
3813房间 大门口 修 地铁 出行 方便1

3814 rows × 2 columns

data.shape[0]*0.8
3051.2000000000003
train_data = data[:3051]
test_data = data[3051:]
train_data
contentsentiment
0年前 老公 夏威夷 选择 同程 这次 国内游 满意 厦门 当地 导游 比较 热情 接机 准时...0
1想 如实 写出 感受 第一天 自由 行 晚上 六点 第二天 云水 谣 领队 郑 导游 联系 ...2
2厦门 这次 游玩 满意 游玩 开心 安排 星 酒店 不错 住 舒适 出门 公交 出行 方便 ...0
3这次 自由 行 比较满意 住 五星级 酒店 泛太平洋 地理位置 不错 市区 这次 坐 动车 ...0
4买 经停 飞机 商量 信誉 大打折扣2
.........
3046四天 行程 满满的 机场 泛太平洋 酒店 打个 滴滴 方便 二十多块 就够 酒店 服务 好 ...0
3047这次 厦门 之旅 同伴 鼓浪屿 日光岩 点 意外 得到 同程 客服 人员 积极 配合 特别 ...0
3048满意 一次 旅行 同程 服务 好 每次 提前 提醒 告知 酒店 不错 服务 好 设施 一流0
3049这次 厦门 旅让 感到 满意 何导 何仙姑 服务 贴心 周到 满足 要求 接送 机 小张 师...0
3050酒店 不错 交通 方便 建议 中山 街 不去 厝 垵 鼓浪屿 必去 厦大 芙蓉 隧道 比较 ...0

3051 rows × 2 columns

test_data
contentsentiment
3051想 朋友 厦门 玩 先后 换 三四次 线路 最后 选 自由 行机 加酒 套餐 整体 不错 酒...0
3052玩 不错0
3053同程 老客户 这次 帮贵社 推荐 位 朋友 想 感受 下夏门 金 钻 会议 之后 变化 顺便...1
3054玩过 之后 觉得 鼓浪屿 住 一晚 这样的话 鼓浪屿 玩会 担心 晚上 再 返回 市里 酒店...0
3055总体 这次 旅行 休闲 娱乐 找 愉快 天 行程 每天 投诉 电话 关键 投诉 解决问题 速...2
.........
3809出游 安排 合理 导游 服务 棒棒 哒0
3810鼓浪屿 导游 服务 好0
3811玩 开心 好评0
3812回来 航班 延误 小时 机上 空乘 个个 帅哥 哈哈哈哈 第二次 厦门 总体 不错 八市 海...0
3813房间 大门口 修 地铁 出行 方便1

763 rows × 2 columns

train_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3051 entries, 0 to 3050
Data columns (total 2 columns):
content      3051 non-null object
sentiment    3051 non-null int64
dtypes: int64(1), object(1)
memory usage: 47.8+ KB
test_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 763 entries, 3051 to 3813
Data columns (total 2 columns):
content      763 non-null object
sentiment    763 non-null int64
dtypes: int64(1), object(1)
memory usage: 12.1+ KB
x_train = train_data["content"]
y_train = train_data["sentiment"]

x_test = test_data["content"]
y_test = test_data["sentiment"]
# from sklearn.model_selection import train_test_split
# x_train,x_test,y_train,y_test = train_test_split(data["content"],data["sentiment"],test_size=0.2,random_state=10)
# print("训练集样本数:",y_train.shape[0],"测试集样本数:",y_test.shape[0])
from sklearn.feature_extraction.text import TfidfVectorizer
vec = TfidfVectorizer()
x_train_tran = vec.fit_transform(x_train)
x_test_tran = vec.transform(x_test)
display(x_train_tran,x_test_tran)
#c = CountVectorizer()
#bag = c.fit_transform(x_train)
#print(c.get_feature_names())  # 注意,在中文中也是不会对单个的汉字进行特征值化,即单个字符被省去了
#print(bag.toarray())
#print(c.vocabulary_)
<3051x13568 sparse matrix of type '<class 'numpy.float64'>'
	with 96220 stored elements in Compressed Sparse Row format>



<763x13568 sparse matrix of type '<class 'numpy.float64'>'
	with 21996 stored elements in Compressed Sparse Row format>
from sklearn.feature_selection import f_classif
f_classif(x_train_tran,y_train)
(array([0.1713417 , 3.18935482, 0.1713417 , ..., 0.1713417 , 0.1713417 ,
        0.1713417 ]),
 array([0.84254174, 0.04133597, 0.84254174, ..., 0.84254174, 0.84254174,
        0.84254174]))
#df=pd.DataFrame({'content':data['content'],'label':data['sentiment']})
#print(df.tail())
#df.dtypes
from sklearn.feature_selection import SelectKBest

x_train_tran = x_train_tran.astype(np.float64)
x_test_tran = x_test_tran.astype(np.float64)
selector = SelectKBest(f_classif,k=min(1000,x_train_tran.shape[1]))
selector.fit(x_train_tran,y_train)
x_train_tran = selector.transform(x_train_tran)
x_test_tran = selector.transform(x_test_tran)
print(x_train_tran.shape,x_test_tran.shape)
(3051, 1000) (763, 1000)

模型

#KNN
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report 
from sklearn.metrics import accuracy_score  
from sklearn.metrics import precision_score, recall_score, f1_score
#param = {'n_neighbors':[5,7],
 #        'weights':['uniform','distance']}
#gs = GridSearchCV(estimator=KNeighborsClassifier(),param_grid=param,
  #               cv=2,scoring="f1",n_jobs=-1,verbose=10)
#gs.fit(x_train_tran,y_train)
#print(gs.best_params_)
#y_hat = gs.best_estimator_.predict(x_test_tran)
#print(classification_report(y_test,y_hat))
classifier = KNeighborsClassifier()
classifier.fit(x_train_tran, y_train)
# print(classifier.score(x_test_tran, y_test))
y_pred = classifier.predict(x_test_tran)

p = precision_score(y_test, y_pred, average=None)
r = recall_score(y_test, y_pred, average=None)
f1score = f1_score(y_test, y_pred, average=None)
score = accuracy_score(y_test,y_pred)
print("precision:",p)
print("recall:",r)
print("fscore:",f1score)
print("accuracy:",score)
precision: [0.7661823 0.2       1.       ]
recall: [1.         0.01111111 0.01075269]
fscore: [0.86761406 0.02105263 0.0212766 ]
accuracy: 0.762778505897772
from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier()
classifier.fit(x_train_tran, y_train)
# print(classifier.score(x_test_tran, y_test))
y_pred = classifier.predict(x_test_tran)

p = precision_score(y_test, y_pred, average=None)
r = recall_score(y_test, y_pred, average=None)
f1score = f1_score(y_test, y_pred, average=None)
score = accuracy_score(y_test,y_pred)
print("precision:",p)
print("recall:",r)
print("fscore:",f1score)
print("accuracy:",score)
precision: [0.81883024 0.125      0.7962963 ]
recall: [0.98965517 0.01111111 0.46236559]
fscore: [0.89617486 0.02040816 0.58503401]
accuracy: 0.8099606815203145
#决策树
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier()
clf.fit(x_train_tran,y_train)
# print(classifier.score(x_test_tran, y_test))
y_pred = clf.predict(x_test_tran)

p = precision_score(y_test, y_pred, average=None)
r = recall_score(y_test, y_pred, average=None)
f1score = f1_score(y_test, y_pred, average=None)
score = accuracy_score(y_test,y_pred)
print("precision:",p)
print("recall:",r)
print("fscore:",f1score)
print("accuracy:",score)
precision: [0.84271523 0.18055556 0.54022989]
recall: [0.87758621 0.14444444 0.50537634]
fscore: [0.8597973  0.16049383 0.52222222]
accuracy: 0.745740498034076

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
import time
import datetime

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.utils import class_weight as cw

from keras import Sequential

from keras.models import Model

from keras.layers import LSTM,Activation,Dense,Dropout,Input,Embedding,BatchNormalization,Add,concatenate,Flatten
from keras.layers import Conv1D,Conv2D,Convolution1D,MaxPool1D,SeparableConv1D,SpatialDropout1D,GlobalAvgPool1D,GlobalMaxPool1D,GlobalMaxPooling1D
from keras.layers.pooling import _GlobalPooling1D
from keras.layers import MaxPooling2D,GlobalMaxPooling2D,GlobalAveragePooling2D
from keras.models import load_model

from keras.optimizers import RMSprop,Adam

from keras.preprocessing.text import Tokenizer
from keras.preprocessing import sequence

from keras.utils import to_categorical

from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint
from keras.callbacks import ReduceLROnPlateau

%matplotlib inline

import warnings
warnings.filterwarnings("ignore")
Using TensorFlow backend.
x_train = train_data["content"]
y_train = train_data["sentiment"]

x_test = test_data["content"]
y_test = test_data["sentiment"]
x_train
0       年前 老公 夏威夷 选择 同程 这次 国内游 满意 厦门 当地 导游 比较 热情 接机 准时...
1       想 如实 写出 感受 第一天 自由 行 晚上 六点 第二天 云水 谣 领队 郑 导游 联系 ...
2       厦门 这次 游玩 满意 游玩 开心 安排 星 酒店 不错 住 舒适 出门 公交 出行 方便 ...
3       这次 自由 行 比较满意 住 五星级 酒店 泛太平洋 地理位置 不错 市区 这次 坐 动车 ...
4                                      买 经停 飞机 商量 信誉 大打折扣
                              ...                        
3046    四天 行程 满满的 机场 泛太平洋 酒店 打个 滴滴 方便 二十多块 就够 酒店 服务 好 ...
3047    这次 厦门 之旅 同伴 鼓浪屿 日光岩 点 意外 得到 同程 客服 人员 积极 配合 特别 ...
3048        满意 一次 旅行 同程 服务 好 每次 提前 提醒 告知 酒店 不错 服务 好 设施 一流
3049    这次 厦门 旅让 感到 满意 何导 何仙姑 服务 贴心 周到 满足 要求 接送 机 小张 师...
3050    酒店 不错 交通 方便 建议 中山 街 不去 厝 垵 鼓浪屿 必去 厦大 芙蓉 隧道 比较 ...
Name: content, Length: 3051, dtype: object
y_train
0       0
1       2
2       0
3       0
4       2
       ..
3046    0
3047    0
3048    0
3049    0
3050    0
Name: sentiment, Length: 3051, dtype: int64
# 分词器Tokenizer   Tokenizer是一个用于向量化文本,或将文本转换为序列(即单词在字典中的下标构成的列表,从1算起)的类
       # 类方法
           # fit_on_texts(texts) :texts用于训练的文本列表
          # texts_to_sequences(texts):texts待转为序列的文本列表 返回值:序列的列表,列表中的每个序列对应于一段输入文本

# 填充序列pad_sequences  将长为nb_smaples的序列转换为(nb_samples,nb_timesteps)2Dnumpy attay.如果提供maxlen,nb_timesteps=maxlen,否则其值为最长序列的长度。
# 其它短于该长度的序列都会在后部填充0以达到该长度。长与nb_timesteps的序列会被阶段,以使其匹配该目标长度。

#max_words = 1000
#max_len = 150
max_words = len(set(" ".join(x_train).split()))
max_len = x_train.apply(lambda x:len(x)).max()


tok = Tokenizer(num_words=max_words)

tok.fit_on_texts(x_train)

sequences = tok.texts_to_sequences(x_train)
sequences_matrix = sequence.pad_sequences(sequences,maxlen=max_len)
# one-hot编码
from keras.utils import to_categorical
y_train = to_categorical(y_train)
y_train
array([[1., 0., 0.],
       [0., 0., 1.],
       [1., 0., 0.],
       ...,
       [1., 0., 0.],
       [1., 0., 0.],
       [0., 1., 0.]], dtype=float32)
# 计算各个类别的weights
def get_weight(y):
    class_weight_current = cw.compute_class_weight("balanced",np.unique(y),y)
    return class_weight_current

class_weight = get_weight(y_train.flatten())
  • sklearn.utils.class_weight 样本均衡

    • 当我们的数据,有多个类别,每个类别的数据量有很大差距时,这时需要对每个类别的样本做一次均衡,这样会让每个类别的特征都在一定程度上被模型学习
  • ModelCheckpoint:

    • 作用:该回调函数将在每个epoch后保存模型到filepath
    • 参数:
      • filename:字符串,保存模型的路径,filepath可以是格式化的字符串,里面的
      • monitor:需要监视的值,通常为:val_acc或val_loss或acc或loss
      • verbose:信息展示模型,0或1。默认为0表示不输出该信息,为1表示输出epoch模型保存信息。
      • save_best_only:当设置为Trur时,将只保存在验证集上性能最好的模型
      • mode:“auto”,“min”,"max"之一,在save_best_only=True时决定性能最佳模型的评判准则。
      • save_weights_only:若设置为True时,则只保存模型权重,否则将保存整个模型(包括模型结构,配置信息等)
      • period:CheckPoint之间的间隔的epoch数
  • EarlyStopping:

    • 作用:当监测值不再改善时,该回调函数将中止训练
    • 参数:
      • monitor:需要监视的量,通常为val_acc或val_loss或acc或loss
      • patience:当early stop被激活(如发现loss相比上patience个epoch训练没有下降),则经过patience个epoch后停止训练。
      • verbose:信息展示模型
      • mode:“auto”,“min”,"max"之一,在min模式下,如果检测值停止下降则中止训练。在max模式下,当检测值不再上升则停止训练。
  • ReduceLROnPlateau:

    • 作用:当评价指标不再提升时,减少学习率。当学习停滞时,减少2倍或10倍的学习率通常能够获得较好的效果。该回调函数检测指标的情况,如果在patience个epoch中看不到模型性能提升,则减少学习率。
    • 参数:
      • monitor:被监测的量
      • factor:每次减少学习率的因子,学习率将以lr=lr*factor的形式被技术那好
      • patience:当patience个epoch过去而模型性能不提升时,学习率减少的动作会被触发
      • mode:“auto”,“min”,"max"之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少
      • epsilon:阈值,用来确定是否进入检测值的“平原区”
      • cooldown:学习率减少后,会经过cooldown个epoch才重新进行正常操作
      • min_lr:学习率的下限。
print("Setting Callbacks")

checkpoint = ModelCheckpoint("model.h5",
                                                     monitor="val_acc",
                                                     save_best_only=True,
                                                     mode="max")

early_stopping = EarlyStopping(monitor="val_loss",
                                                     patience=6,
                                                     verbose=1,
                                                     restore_best_weights=True,
                                                     mode="min")

reduce_lr = ReduceLROnPlateau(monitor="val_loss",
                                                      factor=0.6,
                                                      patience=2,
                                                      verbose=1,
                                                      mode="min")

callbacks=[checkpoint,early_stopping,reduce_lr]

Setting Callbacks
# 定义CNN模型
def CNN():
    model=Sequential()
    
    model.add(Embedding(max_words,100,input_length=max_len))
    
    model.add(Conv1D(64,3,padding="valid",activation="relu",strides=1))
    model.add(Conv1D(128,3,padding="valid",activation="relu",strides=1))
    model.add(Conv1D(256,3,padding="valid",activation="relu",strides=1))

    model.add(GlobalMaxPooling1D())
    model.add(Dense(128,activation="relu"))
    model.add(Dropout(0.25))    
    model.add(Dense(64,activation="relu"))
    model.add(Dense(16,activation="relu"))
    model.add(Dropout(0.25))    
    model.add(Dense(3,activation="softmax"))
    model.summary()
    return model
loss = "categorical_crossentropy"
metrics=["accuracy"]
cnn_model = CNN()
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_2 (Embedding)      (None, 1017, 100)         1669500   
_________________________________________________________________
conv1d_4 (Conv1D)            (None, 1015, 64)          19264     
_________________________________________________________________
conv1d_5 (Conv1D)            (None, 1013, 128)         24704     
_________________________________________________________________
conv1d_6 (Conv1D)            (None, 1011, 256)         98560     
_________________________________________________________________
global_max_pooling1d_2 (Glob (None, 256)               0         
_________________________________________________________________
dense_5 (Dense)              (None, 128)               32896     
_________________________________________________________________
dropout_2 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_6 (Dense)              (None, 64)                8256      
_________________________________________________________________
dense_7 (Dense)              (None, 16)                1040      
_________________________________________________________________
dropout_3 (Dropout)          (None, 16)                0         
_________________________________________________________________
dense_8 (Dense)              (None, 3)                 51        
=================================================================
Total params: 1,854,271
Trainable params: 1,854,271
Non-trainable params: 0
_________________________________________________________________
# CNN模型训练
print("Starting...\n")



print("\n\nCompliling Model...\n")
learning_rate=0.001
optimizer=Adam(learning_rate)
cnn_model.compile(optimizer=optimizer,
                                 loss=loss,
                                 metrics=metrics)

verbose = 1
epochs=100
batch_size=8
validation_split=0.1
print("Trainning Model...\n")
cnn_model = load_model("cnn_model1.h5")

cnn_history=cnn_model.fit(sequences_matrix,
                                            y_train,
                                            batch_size=batch_size,
                                            epochs=epochs,
                                            verbose=1,
                                            callbacks=callbacks,
                                            validation_split=validation_split,
                                            class_weight=class_weight)
Starting...



Compliling Model...

Trainning Model...

Train on 3432 samples, validate on 382 samples
Epoch 1/100
3432/3432 [==============================] - 8s 2ms/step - loss: 0.5437 - accuracy: 0.8033 - val_loss: 0.4385 - val_accuracy: 0.8377
Epoch 2/100
3432/3432 [==============================] - 8s 2ms/step - loss: 0.3397 - accuracy: 0.8601 - val_loss: 0.5063 - val_accuracy: 0.8246
Epoch 3/100
3432/3432 [==============================] - 8s 2ms/step - loss: 0.2460 - accuracy: 0.9024 - val_loss: 0.6464 - val_accuracy: 0.8115

Epoch 00003: ReduceLROnPlateau reducing learning rate to 0.0003600000170990825.
Epoch 4/100
3432/3432 [==============================] - 8s 2ms/step - loss: 0.1551 - accuracy: 0.9464 - val_loss: 0.7178 - val_accuracy: 0.8037
Epoch 5/100
3432/3432 [==============================] - 8s 2ms/step - loss: 0.0879 - accuracy: 0.9729 - val_loss: 0.8973 - val_accuracy: 0.7958

Epoch 00005: ReduceLROnPlateau reducing learning rate to 0.00021600000327453016.
Epoch 6/100
3432/3432 [==============================] - 8s 2ms/step - loss: 0.0572 - accuracy: 0.9843 - val_loss: 1.1212 - val_accuracy: 0.8089
Epoch 7/100
3432/3432 [==============================] - 8s 2ms/step - loss: 0.0346 - accuracy: 0.9898 - val_loss: 1.3203 - val_accuracy: 0.8141
Restoring model weights from the end of the best epoch

Epoch 00007: ReduceLROnPlateau reducing learning rate to 0.00012960000021848827.
Epoch 00007: early stopping
# 将带预测数据转为序列
predict_sequences = tok.texts_to_sequences(x_test)
predict_sequences_matrix = sequence.pad_sequences(predict_sequences,maxlen=max_len)
from keras.models import load_model

y_pred = cnn_model.predict_classes(predict_sequences_matrix)
p = precision_score(y_test, y_pred, average=None)
r = recall_score(y_test, y_pred, average=None)
f1score = f1_score(y_test, y_pred, average=None)
score = accuracy_score(y_test,y_pred)
print("precision:",p)
print("recall:",r)
print("fscore:",f1score)
print("accuracy:",score)
precision: [0.88135593 0.         0.64912281]
recall: [0.9862069  0.         0.79569892]
fscore: [0.93083808 0.         0.71497585]
accuracy: 0.8466579292267365
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mind_programmonkey

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值