import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers import numpy as np import pandas as pd import re
``
import matplotlib.pyplot as plt %matplotlib inline

读取csv文件

1
data = pd.read_csv('Tweets.csv')

获取目标列:’airline_sentiment’,’text’

1
data = data[['airline_sentiment','text']]

统计’airline_sentiment’列

1
2
3
4
5
6
data.airline_sentiment.value_counts()

negative 9178
neutral 3099
positive 2363
Name: airline_sentiment, dtype: int64

正面评价、负面评价归类

1
2
data_p = data[data.airline_sentiment == 'positive']
data_n = data[data.airline_sentiment == 'neutral']

正面评价、负面评价数据量相同

1
data_n = data_n.iloc[:len(data_p)]

数据拼接

1
data = pd.concat([data_n,data_p])

数据乱序

1
data = data.sample(len(data))

从所选的数据的指定 axis 上返回随机抽样结果,类似于random.sample()函数。

positive->0 , neutral->1

1
data['review'] = (data.airline_sentiment == 'positive').astype('int')

删除’airline_sentiment’列

1
del data['airline_sentiment']

正则匹配评论数据(去除表情和无关数据)

1
token = re.compile('[A-Za-z]+|[!?,.()]')
1
2
3
4
def reg_text(text):
new_text = token.findall(text)
new_text = [word.lower() for word in new_text]
return new_text

加载reg_text函数

1
data['text'] = data.text.apply(reg_text)

443 [virginamerica, congrats, vx, on, the, new, ro... 2823 [united, if, i, had, a, ticket, refunded, whic... 14194 [americanair, bershawnjackson, big, ups, to, n... 3981 [united, big, up, the, pilot, of, for, turning... 7781 [jetblue, you, can, t, beat, jetblue, in, spac... ... 7086 [please, explain, ., ., jetblue, our, fleet, s... 3601 [united, vusa, australia, i, m, just, an, auss... 6466 [despite, mother, nature, s, best, efforts, ,,... 5823 [southwestair, good, to, know, ., perhaps, it,... 2563 [united, we, are, trying, to, go, as, far, awa... Name: text, Length: 4726, dtype: object

设置单词字典

1
2
3
4
word_set = set()
for text in data.text:
for word in text:
word_set.add(word)
1
2
word_list = list(word_set)
word_index = dict((word,word_list.index(word)+1) for word in word_list)#将每个单词设置index

将评论单词转化成index

1
data_ok = data.text.apply(lambda x:[word_index.get(word,0) for word in x])

记录最长评论单词数

1
2
maxlen = max(len(x) for x in data_ok)
maxlen

记录单词字典数+1

1
2
max_word = len(word_set) +1
max_word

对数据进行填充

1
data_ok = keras.preprocessing.sequence.pad_sequences(data_ok.values,maxlen=maxlen)#对数据进行填充  根据最长评论长度进行填充

data_ok[0],data_ok.shape
(array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 570, 1321, 1106, 4425, 1443, 1359, 6269, 7359]), (4726, 40))

创建模型

1
2
3
4
model = keras.Sequential()
model.add(layers.Embedding(max_word,50,input_length=maxlen))#输入文本个数,映射成的密集向量长度,输入的文本长度
model.add(layers.LSTM(64))
model.add(layers.Dense(1,activation='sigmoid',use_bias=False))

tf.keras.layers.Embedding 把文本向量化

Embeding:把文本映射为一个密集向量

模型配置

1
2
3
4
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['acc']
)

模型训练

1
history = model.fit(data_ok, data.review.values, epochs=10, batch_size=128, validation_split=0.2)#validation_split  将数据进行切分 切分20%去做测试数据

绘制训练数据变化

1
2
3
plt.plot(history.epoch, history.history.get('val_acc'), c='r', label='val_acc')
plt.plot(history.epoch, history.history.get('acc'), c='b', label='acc')
plt.legend()

1
2
3
plt.plot(history.epoch, history.history.get('val_loss'), c='r', label='val_loss')
plt.plot(history.epoch, history.history.get('loss'), c='b', label='loss')
plt.legend()

模型优化(添加Dropout)

1
2
3
4
5
6
7
8
9
10
11
12
def train_model():
model = keras.Sequential()
model.add(layers.Embedding(max_word, 16, input_length=maxlen))
model.add(layers.LSTM(64,
dropout=0.2,
recurrent_dropout=0.5))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer=keras.optimizers.RMSprop(),
loss='binary_crossentropy',
metrics=['acc'])
return model

dropout:0~1之间的浮点数,控制输入线性变换的神经元断开比例

recurrent_dropout:0~1之间的浮点数,控制循环状态的线性变换的神经元断开比例

1
2
model2 = train_model()
history = model2.fit(data_ok, data.review.values, epochs=10, batch_size=128, validation_split=0.2)#validation_split 数据切分20%的出去作为测试

绘制添加Dropout模型数据变化

1
2
3
plt.plot(history.epoch, history.history.get('val_acc'), c='r', label='val_acc')
plt.plot(history.epoch, history.history.get('acc'), c='b', label='acc')
plt.legend()

1
2
3
plt.plot(history.epoch, history.history.get('val_loss'), c='r', label='val_loss')
plt.plot(history.epoch, history.history.get('loss'), c='b', label='loss')
plt.legend()

模型优化( 使用双向 RNN)

1
2
3
4
5
6
7
8
9
10
11
12
def train_model():
model = keras.Sequential()
model.add(layers.Embedding(max_word, 16, input_length=maxlen))
model.add(layers.Bidirectional(layers.LSTM(64,
dropout=0.2,
recurrent_dropout=0.5)))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer=keras.optimizers.RMSprop(),
loss='binary_crossentropy',
metrics=['acc'])
return model

设置学习速率回调函数

1
learning_rate_reduction = keras.callbacks.ReduceLROnPlateau(monitor='val_loss', patience=3, factor=0.3, min_lr=0.00001)

模型( 双向 RNN)训练

1
2
3
4
5
6
7
model3 = train_model()
history = model3.fit(data_ok,
data.review.values,
epochs=30,
batch_size=128,
validation_split=0.2,
callbacks=[learning_rate_reduction])

绘制训练数据变化

1
2
3
plt.plot(history.epoch, history.history.get('val_acc'), c='r', label='val_acc')
plt.plot(history.epoch, history.history.get('acc'), c='b', label='acc')
plt.legend()

1
2
3
plt.plot(history.epoch, history.history.get('val_loss'), c='r', label='val_loss')
plt.plot(history.epoch, history.history.get('loss'), c='b', label='loss')
plt.legend()