- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章基于循环神经网络(RNN)实现影评情感分类由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
使用循环神经网络(RNN)实现影评情感分类 。
作为对循环神经网络的实践,我用循环神经网络做了个影评情感的分类,即判断影评的感情色彩是正面的,还是负面的.
选择使用RNN来做情感分类,主要是因为影评是一段文字,是序列的,而RNN对序列的支持比较好,能够“记忆”前文。虽然可以提取特征词向量,然后交给传统机器学习模型或全连接神经网络去做,也能取得很好的效果,但只从端对端的角度来看的话,RNN无疑是最合适的.
以下介绍实现过程.
1、数据预处理 。
本文中使用的训练数据集为https://www.cs.cornell.edu/people/pabo/movie-review-data/上的sentence polarity dataset v1.0,包含正负面评论各5331条。可以点击进行下载.
数据下载下来之后需要进行解压,得到rt-polarity.neg和rt-polarity.pos文件,这两个文件是Windows-1252编码的,先将它转成unicode处理起来会更方便.
补充一下小知识,当我们打开一个文件,发现乱码,却又不知道该文件的编码是什么的时候,可以使用python的chardet类库进行判断,这里的Windows-1252就是使用该类库检测出来的.
在数据预处理部分,我们要完成如下处理过程:
1.转码 。
即将文件转为unicode编码,方便我们后续操作。读取文件,转换编码,重新写入到新文件即可。不存在技术难点.
2.生成词汇表 。
读取训练文件,提取出所有的单词,并统计各个单词出现的次数。为了避免低频词的干扰,同时减少模型参数,我们只保留部分高频词,比如这里我只保存出现次数前9999个,同时将低频词标识符<unkown>加入到词汇表中.
3.借助词汇表将影评转化为词向量 。
单词是没法直接输入给模型的,所以我们需要将词汇表中的每个单词对应于一个编号,将影评数据转化成词向量。方便后面生成词嵌入矩阵.
4.填充词向量并转化为np数组 。
因为不同评论的长度是不同的,我们要组成batch进行训练,就需要先将其长度统一。这里我选择以最长的影评为标准,对其他较短的影评的空白部分进行填充。然后将其转化成numpy的数组.
5.按比例划分数据集 。
按照机器学习的惯例,数据集应被划分为三份,即训练集、开发集和测试集。当然,有时也会只划分两份,即只包括训练集和开发集.
这里我划分成三份,训练集、开发集和测试集的占比为[0.8,0.1,0.1]。划分的方式为轮盘赌法,在numpy中可以使用cumsum和searchsorted来简洁地实现轮盘赌法.
6.打乱数据集,写入文件 。
为了取得更好的训练效果,将数据集随机打乱。为了保证在训练和模型调整的过程中训练集、开发集、测试集不发生改变,将三个数据集写入到文件中,使用的时候从文件中读取.
下面贴上数据预处理的代码,注释写的很细,就不多说了.
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
# -*- coding: utf-8 -*-
# @Time : 18-3-14 下午2:28
# @Author : AaronJny
# @Email : Aaron__7@163.com
import
sys
reload
(sys)
sys.setdefaultencoding(
'utf8'
)
import
collections
import
settings
import
utils
import
numpy as np
def
create_vocab():
"""
创建词汇表,写入文件中
:return:
"""
# 存放出现的所有单词
word_list
=
[]
# 从文件中读取数据,拆分单词
with
open
(settings.NEG_TXT,
'r'
) as f:
f_lines
=
f.readlines()
for
line
in
f_lines:
words
=
line.strip().split()
word_list.extend(words)
with
open
(settings.POS_TXT,
'r'
) as f:
f_lines
=
f.readlines()
for
line
in
f_lines:
words
=
line.strip().split()
word_list.extend(words)
# 统计单词出现的次数
counter
=
collections.Counter(word_list)
sorted_words
=
sorted
(counter.items(), key
=
lambda
x: x[
1
], reverse
=
True
)
# 选取高频词
word_list
=
[word[
0
]
for
word
in
sorted_words]
word_list
=
[
'<unkown>'
]
+
word_list[:settings.VOCAB_SIZE
-
1
]
# 将词汇表写入文件中
with
open
(settings.VOCAB_PATH,
'w'
) as f:
for
word
in
word_list:
f.write(word
+
'\n'
)
def
create_vec(txt_path, vec_path):
"""
根据词汇表生成词向量
:param txt_path: 影评文件路径
:param vec_path: 输出词向量路径
:return:
"""
# 获取单词到编号的映射
word2id
=
utils.read_word_to_id_dict()
# 将语句转化成向量
vec
=
[]
with
open
(txt_path,
'r'
) as f:
f_lines
=
f.readlines()
for
line
in
f_lines:
tmp_vec
=
[
str
(utils.get_id_by_word(word, word2id))
for
word
in
line.strip().split()]
vec.append(tmp_vec)
# 写入文件中
with
open
(vec_path,
'w'
) as f:
for
tmp_vec
in
vec:
f.write(
' '
.join(tmp_vec)
+
'\n'
)
def
cut_train_dev_test():
"""
使用轮盘赌法,划分训练集、开发集和测试集
打乱,并写入不同文件中
:return:
"""
# 三个位置分别存放训练、开发、测试
data
=
[[], [], []]
labels
=
[[], [], []]
# 累加概率 rate [0.8,0.1,0.1] cumsum_rate [0.8,0.9,1.0]
rate
=
np.array([settings.TRAIN_RATE, settings.DEV_RATE, settings.TEST_RATE])
cumsum_rate
=
np.cumsum(rate)
# 使用轮盘赌法划分数据集
with
open
(settings.POS_VEC,
'r'
) as f:
f_lines
=
f.readlines()
for
line
in
f_lines:
tmp_data
=
[
int
(word)
for
word
in
line.strip().split()]
tmp_label
=
[
1
, ]
index
=
int
(np.searchsorted(cumsum_rate, np.random.rand(
1
)
*
1.0
))
data[index].append(tmp_data)
labels[index].append(tmp_label)
with
open
(settings.NEG_VEC,
'r'
) as f:
f_lines
=
f.readlines()
for
line
in
f_lines:
tmp_data
=
[
int
(word)
for
word
in
line.strip().split()]
tmp_label
=
[
0
, ]
index
=
int
(np.searchsorted(cumsum_rate, np.random.rand(
1
)
*
1.0
))
data[index].append(tmp_data)
labels[index].append(tmp_label)
# 计算一下实际上分割出来的比例
print
'最终分割比例'
, np.array([
map
(
len
, data)], dtype
=
np.float32)
/
sum
(
map
(
len
, data))
# 打乱数据,写入到文件中
shuffle_data(data[
0
], labels[
0
], settings.TRAIN_DATA)
shuffle_data(data[
1
], labels[
1
], settings.DEV_DATA)
shuffle_data(data[
2
], labels[
2
], settings.TEST_DATA)
def
shuffle_data(x, y, path):
"""
填充数据,生成np数组
打乱数据,写入文件中
:param x: 数据
:param y: 标签
:param path: 保存路径
:return:
"""
# 计算影评的最大长度
maxlen
=
max
(
map
(
len
, x))
# 填充数据
data
=
np.zeros([
len
(x), maxlen], dtype
=
np.int32)
for
row
in
range
(
len
(x)):
data[row, :
len
(x[row])]
=
x[row]
label
=
np.array(y)
# 打乱数据
state
=
np.random.get_state()
np.random.shuffle(data)
np.random.set_state(state)
np.random.shuffle(label)
# 保存数据
np.save(path
+
'_data'
, data)
np.save(path
+
'_labels'
, label)
def
decode_file(infile, outfile):
"""
将文件的编码从'Windows-1252'转为Unicode
:param infile: 输入文件路径
:param outfile: 输出文件路径
:return:
"""
with
open
(infile,
'r'
) as f:
txt
=
f.read().decode(
'Windows-1252'
)
with
open
(outfile,
'w'
) as f:
f.write(txt)
if
__name__
=
=
'__main__'
:
# 解码文件
decode_file(settings.ORIGIN_POS, settings.POS_TXT)
decode_file(settings.ORIGIN_NEG, settings.NEG_TXT)
# 创建词汇表
create_vocab()
# 生成词向量
create_vec(settings.NEG_TXT, settings.NEG_VEC)
create_vec(settings.POS_TXT, settings.POS_VEC)
# 划分数据集
cut_train_dev_test()
|
2、模型编写 。
数据处理好之后,开始模型的编写。这里选用循环神经网络,建模过程大致如下:
1.使用embedding构建词嵌入矩阵 。
在数据预处理中,我们将影评处理成了一个个单词编号构成的向量,也就是说,一条影评,对应于一个由单词编号构成的向量.
将这样的向量进行embedding,即可构建出词嵌入矩阵。在词嵌入矩阵中,每个词由一个向量表示,矩阵中不同向量之间的差异对应于它们表示的词之间的差异.
2.使用LSTM作为循环神经网络的基本单元 。
长短时记忆网络(LSTM)能够自动完成前文信息的“记忆”和“遗忘”,在循环神经网络中表现良好,已经成为在循环神经网络中大部分人的首选。这里我选择使用LSTM作为循环神经网络的基本单元.
3.对embedding和LSTM进行随机失活(dropout) 。
为了提高模型的泛化能力,并减少参数,我对embedding层和LSTM单元进行dropout.
4.建立深度为2的深度循环神经网络 。
为了提高模型的拟合能力,使用深度循环神经网络,我选择的深度为2.
5.给出二分类概率 。
对深度循环神经网络的最后节点的输出做逻辑回归,通过sigmoid使结果落到0-1之间,代表结果是正类的概率.
损失函数使用交叉熵,优化器选择Adam.
此部分代码如下(注:代码中装饰器的作用为划分命名空间以及保证张量运算只被定义一次):
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
# -*- coding: utf-8 -*-
# @Time : 18-3-14 下午2:57
# @Author : AaronJny
# @Email : Aaron__7@163.com
import
tensorflow as tf
import
functools
import
settings
HIDDEN_SIZE
=
128
NUM_LAYERS
=
2
def
doublewrap(function):
@functools
.wraps(function)
def
decorator(
*
args,
*
*
kwargs):
if
len
(args)
=
=
1
and
len
(kwargs)
=
=
0
and
callable
(args[
0
]):
return
function(args[
0
])
else
:
return
lambda
wrapee: function(wrapee,
*
args,
*
*
kwargs)
return
decorator
@doublewrap
def
define_scope(function, scope
=
None
,
*
args,
*
*
kwargs):
attribute
=
'_cache_'
+
function.__name__
name
=
scope
or
function.__name__
@property
@functools
.wraps(function)
def
decorator(
self
):
if
not
hasattr
(
self
, attribute):
with tf.variable_scope(name,
*
args,
*
*
kwargs):
setattr
(
self
, attribute, function(
self
))
return
getattr
(
self
, attribute)
return
decorator
class
Model(
object
):
def
__init__(
self
, data, lables, emb_keep, rnn_keep):
"""
神经网络模型
:param data:数据
:param lables: 标签
:param emb_keep: emb层保留率
:param rnn_keep: rnn层保留率
"""
self
.data
=
data
self
.label
=
lables
self
.emb_keep
=
emb_keep
self
.rnn_keep
=
rnn_keep
self
.predict
self
.loss
self
.global_step
self
.ema
self
.optimize
self
.acc
@define_scope
def
predict(
self
):
"""
定义前向传播过程
:return:
"""
# 词嵌入矩阵权重
embedding
=
tf.get_variable(
'embedding'
, [settings.VOCAB_SIZE, HIDDEN_SIZE])
# 使用dropout的LSTM
lstm_cell
=
[tf.nn.rnn_cell.DropoutWrapper(tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE),
self
.rnn_keep)
for
_
in
range
(NUM_LAYERS)]
# 构建循环神经网络
cell
=
tf.nn.rnn_cell.MultiRNNCell(lstm_cell)
# 生成词嵌入矩阵,并进行dropout
input
=
tf.nn.embedding_lookup(embedding,
self
.data)
dropout_input
=
tf.nn.dropout(
input
,
self
.emb_keep)
# 计算rnn的输出
outputs, last_state
=
tf.nn.dynamic_rnn(cell, dropout_input, dtype
=
tf.float32)
# 做二分类问题,这里只需要最后一个节点的输出
last_output
=
outputs[:,
-
1
, :]
# 求最后节点输出的线性加权和
weights
=
tf.Variable(tf.truncated_normal([HIDDEN_SIZE,
1
]), dtype
=
tf.float32, name
=
'weights'
)
bias
=
tf.Variable(
0
, dtype
=
tf.float32, name
=
'bias'
)
logits
=
tf.matmul(last_output, weights)
+
bias
return
logits
@define_scope
def
ema(
self
):
"""
定义移动平均
:return:
"""
ema
=
tf.train.ExponentialMovingAverage(settings.EMA_RATE,
self
.global_step)
return
ema
@define_scope
def
loss(
self
):
"""
定义损失函数,这里使用交叉熵
:return:
"""
loss
=
tf.nn.sigmoid_cross_entropy_with_logits(labels
=
self
.label, logits
=
self
.predict)
loss
=
tf.reduce_mean(loss)
return
loss
@define_scope
def
global_step(
self
):
"""
step,没什么好说的,注意指定trainable=False
:return:
"""
global_step
=
tf.Variable(
0
, trainable
=
False
)
return
global_step
@define_scope
def
optimize(
self
):
"""
定义反向传播过程
:return:
"""
# 学习率衰减
learn_rate
=
tf.train.exponential_decay(settings.LEARN_RATE,
self
.global_step, settings.LR_DECAY_STEP,
settings.LR_DECAY)
# 反向传播优化器
optimizer
=
tf.train.AdamOptimizer(learn_rate).minimize(
self
.loss, global_step
=
self
.global_step)
# 移动平均操作
ave_op
=
self
.ema.
apply
(tf.trainable_variables())
# 组合构成训练op
with tf.control_dependencies([optimizer, ave_op]):
train_op
=
tf.no_op(
'train'
)
return
train_op
@define_scope
def
acc(
self
):
"""
定义模型acc计算过程
:return:
"""
# 对前向传播的结果求sigmoid
output
=
tf.nn.sigmoid(
self
.predict)
# 真负类
ok0
=
tf.logical_and(tf.less_equal(output,
0.5
), tf.equal(
self
.label,
0
))
# 真正类
ok1
=
tf.logical_and(tf.greater(output,
0.5
), tf.equal(
self
.label,
1
))
# 一个数组,所有预测正确的都为True,否则False
ok
=
tf.logical_or(ok0, ok1)
# 先转化成浮点型,再通过求平均来计算acc
acc
=
tf.reduce_mean(tf.cast(ok, dtype
=
tf.float32))
return
acc
|
3、组织数据集 。
我编写了一个类用于组织数据,方便训练和验证使用。代码很简单,就不多说了,直接贴代码:
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
# -*- coding: utf-8 -*-
# @Time : 18-3-14 下午3:33
# @Author : AaronJny
# @Email : Aaron__7@163.com
import
numpy as np
import
settings
class
Dataset(
object
):
def
__init__(
self
, data_kind
=
0
):
"""
生成一个数据集对象
:param data_kind: 决定了使用哪种数据集 0-训练集 1-开发集 2-测试集
"""
self
.data,
self
.labels
=
self
.read_data(data_kind)
self
.start
=
0
# 记录当前batch位置
self
.data_size
=
len
(
self
.data)
# 样例数
def
read_data(
self
, data_kind):
"""
从文件中加载数据
:param data_kind:数据集种类 0-训练集 1-开发集 2-测试集
:return:
"""
# 获取数据集路径
data_path
=
[settings.TRAIN_DATA, settings.DEV_DATA, settings.TEST_DATA][data_kind]
# 加载
data
=
np.load(data_path
+
'_data.npy'
)
labels
=
np.load(data_path
+
'_labels.npy'
)
return
data, labels
def
next_batch(
self
, batch_size):
"""
获取一个大小为batch_size的batch
:param batch_size: batch大小
:return:
"""
start
=
self
.start
end
=
min
(start
+
batch_size,
self
.data_size)
self
.start
=
end
# 当遍历完成后回到起点
if
self
.start >
=
self
.data_size:
self
.start
=
0
# 返回一个batch的数据和标签
return
self
.data[start:end],
self
.labels[start:end]
|
4、模型训练 。
训练过程中,额外操作主要有两个:
1.使用移动平均 。
我使用移动平均的主要目的是使loss曲线尽量平滑,以及提升模型的泛化能力.
2.使用学习率指数衰减 。
目的是保证前期学习率足够大,能够快速降低loss,后期学习率变小,能更好地逼近最优解.
当然,就是说说而已,这次的训练数据比较简单,学习率衰减发挥的作用不大.
训练过程中,定期保存模型,以及checkpoint。这样可以在训练的同时,在验证脚本中读取最新模型进行验证.
此部分具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
# -*- coding: utf-8 -*-
# @Time : 18-3-14 下午4:41
# @Author : AaronJny
# @Email : Aaron__7@163.com
import
settings
import
tensorflow as tf
import
models
import
dataset
import
os
BATCH_SIZE
=
settings.BATCH_SIZE
# 数据
x
=
tf.placeholder(tf.int32, [
None
,
None
])
# 标签
y
=
tf.placeholder(tf.float32, [
None
,
1
])
# emb层的dropout保留率
emb_keep
=
tf.placeholder(tf.float32)
# rnn层的dropout保留率
rnn_keep
=
tf.placeholder(tf.float32)
# 创建一个模型
model
=
models.Model(x, y, emb_keep, rnn_keep)
# 创建数据集对象
data
=
dataset.Dataset(
0
)
saver
=
tf.train.Saver()
with tf.Session() as sess:
# 全局初始化
sess.run(tf.global_variables_initializer())
# 迭代训练
for
step
in
range
(settings.TRAIN_TIMES):
# 获取一个batch进行训练
x, y
=
data.next_batch(BATCH_SIZE)
loss, _
=
sess.run([model.loss, model.optimize],
{model.data: x, model.label: y, model.emb_keep: settings.EMB_KEEP_PROB,
model.rnn_keep: settings.RNN_KEEP_PROB})
# 输出loss
if
step
%
settings.SHOW_STEP
=
=
0
:
print
'step {},loss is {}'
.
format
(step, loss)
# 保存模型
if
step
%
settings.SAVE_STEP
=
=
0
:
saver.save(sess, os.path.join(settings.CKPT_PATH, settings.MODEL_NAME), model.global_step)
|
5、验证模型 。
加载最新模型进行验证,通过修改数据集对象的参数可以制定训练/开发/测试集进行验证.
加载模型的时候,使用移动平均的影子变量覆盖对应变量.
代码如下:
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
# -*- coding: utf-8 -*-
# @Time : 18-3-14 下午5:09
# @Author : AaronJny
# @Email : Aaron__7@163.com
import
settings
import
tensorflow as tf
import
models
import
dataset
import
os
import
time
# 为了在使用GPU训练的同时,使用CPU进行验证
os.environ[
'CUDA_VISIBLE_DEVICES'
]
=
''
BATCH_SIZE
=
settings.BATCH_SIZE
# 数据
x
=
tf.placeholder(tf.int32, [
None
,
None
])
# 标签
y
=
tf.placeholder(tf.float32, [
None
,
1
])
# emb层的dropout保留率
emb_keep
=
tf.placeholder(tf.float32)
# rnn层的dropout保留率
rnn_keep
=
tf.placeholder(tf.float32)
# 创建一个模型
model
=
models.Model(x, y, emb_keep, rnn_keep)
# 创建一个数据集对象
data
=
dataset.Dataset(
1
)
# 0-训练集 1-开发集 2-测试集
# 移动平均变量
restore_variables
=
model.ema.variables_to_restore()
# 使用移动平均变量进行覆盖
saver
=
tf.train.Saver(restore_variables)
with tf.Session() as sess:
while
True
:
# 加载最新的模型
ckpt
=
tf.train.get_checkpoint_state(settings.CKPT_PATH)
saver.restore(sess, ckpt.model_checkpoint_path)
# 计算并输出acc
acc
=
sess.run([model.acc],
{model.data: data.data, model.label: data.labels, model.emb_keep:
1.0
, model.rnn_keep:
1.0
})
print
'acc is '
, acc
time.sleep(
1
)
|
6、对词汇表进行操作的几个方法 。
把对词汇表进行操作的几个方法提取出来了,放到了utils.py文件中.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
# -*- coding: utf-8 -*-
# @Time : 18-3-14 下午2:44
# @Author : AaronJny
# @Email : Aaron__7@163.com
import
settings
def
read_vocab_list():
"""
读取词汇表
:return:由词汇表中所有单词组成的列表
"""
with
open
(settings.VOCAB_PATH,
'r'
) as f:
vocab_list
=
f.read().strip().split(
'\n'
)
return
vocab_list
def
read_word_to_id_dict():
"""
生成一个单词到编号的映射
:return:单词到编号的字典
"""
vocab_list
=
read_vocab_list()
word2id
=
dict
(
zip
(vocab_list,
range
(
len
(vocab_list))))
return
word2id
def
read_id_to_word_dict():
"""
生成一个编号到单词的映射
:return:编号到单词的字典
"""
vocab_list
=
read_vocab_list()
id2word
=
dict
(
zip
(
range
(
len
(vocab_list)), vocab_list))
return
id2word
def
get_id_by_word(word, word2id):
"""
给定一个单词和字典,获得单词在字典中的编号
:param word: 给定单词
:param word2id: 单词到编号的映射
:return: 若单词在字典中,返回对应的编号 否则,返回word2id['<unkown>']
"""
if
word
in
word2id:
return
word2id[word]
else
:
return
word2id[
'<unkown>'
]
|
7、对模型进行配置 。
模型的配置参数大多数都被提取出来,单独放到了settings.py文件中,可以在这里对模型进行配置.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
# -*- coding: utf-8 -*-
# @Time : 18-3-14 下午2:44
# @Author : AaronJny
# @Email : Aaron__7@163.com
# 源数据路径
ORIGIN_NEG
=
'data/rt-polarity.neg'
ORIGIN_POS
=
'data/rt-polarity.pos'
# 转码后的数据路径
NEG_TXT
=
'data/neg.txt'
POS_TXT
=
'data/pos.txt'
# 词汇表路径
VOCAB_PATH
=
'data/vocab.txt'
# 词向量路径
NEG_VEC
=
'data/neg.vec'
POS_VEC
=
'data/pos.vec'
# 训练集路径
TRAIN_DATA
=
'data/train'
# 开发集路径
DEV_DATA
=
'data/dev'
# 测试集路径
TEST_DATA
=
'data/test'
# 模型保存路径
CKPT_PATH
=
'ckpt'
# 模型名称
MODEL_NAME
=
'model'
# 词汇表大小
VOCAB_SIZE
=
10000
# 初始学习率
LEARN_RATE
=
0.0001
# 学习率衰减
LR_DECAY
=
0.99
# 衰减频率
LR_DECAY_STEP
=
1000
# 总训练次数
TRAIN_TIMES
=
2000
# 显示训练loss的频率
SHOW_STEP
=
10
# 保存训练模型的频率
SAVE_STEP
=
100
# 训练集占比
TRAIN_RATE
=
0.8
# 开发集占比
DEV_RATE
=
0.1
# 测试集占比
TEST_RATE
=
0.1
# BATCH大小
BATCH_SIZE
=
64
# emb层dropout保留率
EMB_KEEP_PROB
=
0.5
# rnn层dropout保留率
RNN_KEEP_PROB
=
0.5
# 移动平均衰减率
EMA_RATE
=
0.99
|
8、运行模型 。
至此,模型构建完成。模型的运行步骤大致如下:
1.确保数据文件放在了对应路径中,运行python process_data对数据进行预处理.
2.运行python train.py对模型进行训练,训练好的模型会自动保存到对应的路径中.
3.运行python eval.py读取保存的最新模型,对训练/开发/测试集进行验证.
我简单跑了一下,由于数据集较小,模型的泛化能力不是很好.
当训练集、开发集、测试集的分布为[0.8,0.1,0.1],训练2000个batch_size=64的mini_batch时,模型在各数据集上的acc表现大致如下:
训练集 0.95 。
开发集 0.79 。
测试集 0.80 。
更多 。
转行做机器学习,要学的还很多,文中如有错误纰漏之处,恳请诸位大佬拍砖指教… 。
项目GitHub地址:https://github.com/AaronJny/emotional_classification_with_rnn 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://blog.csdn.net/aaronjny/article/details/79561115 。
最后此篇关于基于循环神经网络(RNN)实现影评情感分类的文章就讲到这里了,如果你想了解更多关于基于循环神经网络(RNN)实现影评情感分类的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在使用reactjs-popup,它的 Prop 之一是contentStyle,它允许您传递css-in-js对象来设置库中内部div的样式。 但是,当我传递带有 @media 的 css 对象
在查看了一些服务/工具之后,我得出了一个结论。大多数 Text-to-Speech 工具的技术含量太高、太机械化——换句话说,就是质量差的 c 语音。 是的,最重要的是,看起来它们带有“硬编码”语音模
我正在尝试使用 Emotion.sh在我的 React 测试元素中,但我使用与 example 中相同的代码得到以下错误 需要考虑的可能有冲突的事情:1、之前用的是npm,现在用的是yarn;2. 我
通过以下链接,我有了一些想法。我想问问我是做对了还是做错了。如果我走错了路,请指导我。 链接 Using libsvm for text classification c# How to use li
以下设置不显示background-image。作为调试步骤,我尝试在 const background 中设置 background: pink,这确实有效,确认 emotion 正在正确运行。 打
我有一个 data.frame,其中包含周数 week 和文本评论 text。我想将 week 变量视为我的分组变量,并对它运行一些基本的文本分析(例如 qdap::polarity)。一些评论文本有
我正在研究 Kaggle 电影情感分析,我发现电影评论已使用 Standford Parser 进行了解析。在探索数据集时,我发现相同的语句给出了不同的设置- their parents , wise
我正在尝试使用Affectiva emotion sdk 制作一个演示程序。但是,当我调用 detector.setLicensePath() 时,会抛出一个异常(见下图)。有谁知道如何解决这个问题?
我想设置一个使用 Material-UI v4.11.4 的 Typescript 项目来使用情感进行样式设置,为 MUI v5 版本做准备。目标是在项目中引入情感,以便开发人员可以开始使用新样式,而
我是一名优秀的程序员,十分优秀!