制作数据集及CNN搭建(1)
因为CNN是根据卷积核来扫描矩阵,而卷积核的选取通常为3*3,因此我的数据集选取与别人的数据集不同,对数据源的格式要求比较多,因此我选取256*256的向量。
首先,使用结巴分词器来分词,在使用word2vec训练数据,获取词向量。word2vec是在独热码的基础上,运用神经网络来加强的词向量的距离的计算。大概了解一下word2vec的运行流程。
(1) 分词 / 词干提取和词形还原。 中文和英文的nlp各有各的难点,中文的难点在于需要进行分词,将一个个句子分解成一个单词数组。而英文虽然不需要分词,但是要处理各种各样的时态,所以要进行词干提取和词形还原。
(2) 构造词典,统计词频。这一步需要遍历一遍所有文本,找出所有出现过的词,并统计各词的出现频率。
(3) 构造树形结构。依照出现概率构造Huffman树。如果是完全二叉树,则简单很多,后面会仔细解释。需要注意的是,所有分类都应该处于叶节点,像下图显示的那样
(4)生成节点所在的二进制码。拿上图举例,22对应的二进制码为00,而17对应的是100。也就是说,这个二进制码反映了节点在树中的位置,就像门牌号一样,能按照编码从根节点一步步找到对应的叶节点。
(5) 初始化各非叶节点的中间向量和叶节点中的词向量。树中的各个节点,都存储着一个长为m的向量,但叶节点和非叶结点中的向量的含义不同。叶节点中存储的是各词的词向量,是作为神经网络的输入的。而非叶结点中存储的是中间向量,对应于神经网络中隐含层的参数,与输入一起决定分类结果。
(6) 训练中间向量和词向量。对于CBOW模型,首先将词A附近的n-1个词的词向量相加作为系统的输入,并且按照词A在步骤4中生成的二进制码,一步步的进行分类并按照分类结果训练中间向量和词向量。举个栗子,对于绿17节点,我们已经知道其二进制码是100。那么在第一个中间节点应该将对应的输入分类到右边。如果分类到左边,则表明分类错误,需要对向量进行修正。第二个,第三个节点也是这样,以此类推,直到达到叶节点。因此对于单个单词来说,最多只会改动其路径上的节点的中间向量,而不会改动其他节点。
至此,训练好的数据如下所示:
随后,可以开始搭建CNN:
第一步.读取数据集中的数据:
按照训练5,测试1的比例划分数据集:
# 读取数据函数,返回list类型的训练数据集和测试数据集
def loadData(fileName):
trainingData = []
testData = []
count = 0
with open(fileName) as txtData:
lines = txtData.readlines()
for line in lines:
linedata = line.split(" ")
linedata = list(map(float, linedata))
count = count + 1
# 数据集分割比例
if count % 5 != 0:
# 训练数据集
trainingData.append(linedata)
else:
# 测试数据集
testData.append(linedata)
return trainingData, testData
构建系统参数:
# 将权重初始化
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
# 将偏置初始化
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
# 定义卷积函数conv2d
def conv2d(x, W):
# stride [1, x_movement, y_movement, 1]
# Must have strides[0] = strides[3] = 1
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding="SAME")
# 定义池化函数,池化过程采取max pool策略
def max_pool_2x2(x):
# stride [1, x_movement, y_movement, 1]
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
计算准确度:
def compute_accuracy(v_xs, v_ys):
# 全局变量 -- 预测结果
global prediction
# 运行预测
y_pre = sess.run(prediction, feed_dict={xs: v_xs, keep_prob: 1}) # feed_dict 字典
# 定义正确预测
correct_prediction = tf.equal(tf.argmax(y_pre, 1), tf.argmax(v_ys, 1)) # 相同返回1 不相同返回0
# 定义准确度度量
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # (0,1)数据的平均值就是其准确度
# 运行计算准确度
result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys, keep_prob: 1}) # xs:400维的向量 ys:好中差标签
return result