word2vec词向量 文本分类实现(TensorFlow版,算法TextCNN)
之前也寫過word2vec詞向量文本分類實現,不過那是基于Keras。
今天來寫下tensoflow版的代碼。
再來感受下它的魅力。
tensorflow比Keras更接近底層,可以更方便讓我們理解Word2vector如何應用在文本分類中
簡化版例子。
之前的文本分類博客鏈接:
基于詞向量word2vec模型的文本分類實現(算例有代碼 Keras版)
短文本分類:電力95598工單分類實現 tf-idf
算例
第一步:導入包
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # @Author: yudengwu # @Date : 2020/9/6import tensorflow as tf import numpy as np第二步:數據
為了方便,我只列出啦其個樣本,且樣本為英文。如果是中文,那么代碼里的sentences應該為分詞并去除停用詞后的數據。
本例子中樣本有的長度為3,有的為2。對應現實生活中不同長度的文本。
如果是中文例子,則長度指的是(分詞并去除停用詞后)樣本包含詞語的個數。
labels為標簽,簡單2分類操作。
第三步:獲取詞典
word_dict = {w: i+1 for i, w in enumerate(word_list)}
字典中i來說一般不加1,默認從0 開始 ,我這里加1。是因為我后面要為斷文本填0操作,使各個文本長度一致,是填充的0和原始字典0區別開來,所有字典中的i+1。
word_dict:
{‘she’: 1, ‘for’: 2, ‘baseball’: 3, ‘that’: 4, ‘me’: 5, ‘loves’: 6, ‘likes’: 7, ‘hate’: 8, ‘this’: 9, ‘you’: 10, ‘i’: 11, ‘awful’: 12, ‘is’: 13, ‘sorry’: 14, ‘love’: 15, ‘he’: 16}
vocab_size:
16
vocab_size=詞語數+1,+1代表填充的0,代表未知詞,后面用到
第四步:設置參數
num_list=[len(one.split()) for one in sentences]#[3, 2, 3, 3, 3, 2, 3, 3]
sequence_length = max(num_list)#求取最大文本長度3
這兩行代碼為獲取最大文本長度
第五步:輸入輸出處理
inputs = [] for sen in sentences:c=[word_dict[n] for n in sen.split()]#if len(c)<=sequence_length:c.extend([0 for i in range(sequence_length-len(c))])inputs.append(np.array(c)) outputs = [] for out in labels:outputs.append(np.eye(num_classes)[out]) # ONE-HOT : To using Tensor Softmax Loss function print('inputs',inputs) print('outputs',outputs)inputs [array([ 2, 15, 7]), array([15, 7, 0]), array([ 6, 14, 16]), array([13, 5, 8]), array([2, 3, 7]), array([3, 7, 0]), array([ 9, 10, 11]), array([ 4, 1, 12])]
outputs [array([0., 1.]), array([0., 1.]), array([0., 1.]), array([0., 1.]), array([1., 0.]), array([1., 0.]), array([1., 0.]), array([1., 0.])]
通過以上處理我們成功將文本用數值數據表示啦出來,可以將此數據拿到任意一個分類模型進行訓練。
這種文本表示方法存在弊端,如果樣本中只有一個長文本,其他全是短文本,則短文本表示中有很多為0,存在稀疏性問題。這個問題我們通過模型解決。
這種表示像是詞典模型的變種。
第六步:模型
# Model X = tf.placeholder(tf.int32, [None, sequence_length]) Y = tf.placeholder(tf.int32, [None, num_classes])W = tf.Variable(tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0)) embedded_chars = tf.nn.embedding_lookup(W, X) # [batch_size, sequence_length, embedding_size] embedded_chars = tf.expand_dims(embedded_chars, -1) # add channel(=1) [batch_size, sequence_length, embedding_size, 1]pooled_outputs = [] for i, filter_size in enumerate(filter_sizes):filter_shape = [filter_size, embedding_size, 1, num_filters]W = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1))b = tf.Variable(tf.constant(0.1, shape=[num_filters]))conv = tf.nn.conv2d(embedded_chars, # [batch_size, sequence_length, embedding_size, 1]W, # [filter_size(n-gram window), embedding_size, 1, num_filters(=3)]strides=[1, 1, 1, 1],padding='VALID')h = tf.nn.relu(tf.nn.bias_add(conv, b))pooled = tf.nn.max_pool(h,ksize=[1, sequence_length - filter_size + 1, 1, 1], # [batch_size, filter_height, filter_width, channel]strides=[1, 1, 1, 1],padding='VALID')pooled_outputs.append(pooled) # dim of pooled : [batch_size(=6), output_height(=1), output_width(=1), channel(=1)]num_filters_total = num_filters * len(filter_sizes) h_pool = tf.concat(pooled_outputs, num_filters) # h_pool : [batch_size(=6), output_height(=1), output_width(=1), channel(=1) * 3] h_pool_flat = tf.reshape(h_pool, [-1, num_filters_total]) # [batch_size, ]# Model-Training Weight = tf.get_variable('W', shape=[num_filters_total, num_classes], initializer=tf.contrib.layers.xavier_initializer()) Bias = tf.Variable(tf.constant(0.1, shape=[num_classes])) model = tf.nn.xw_plus_b(h_pool_flat, Weight, Bias) cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y)) optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)# Model-Predict hypothesis = tf.nn.softmax(model) predictions = tf.argmax(hypothesis, 1)解釋:tf.random_uniform((4, 4), minval=low,maxval=high,dtype=tf.float32)))返回4*4的矩陣,產生于low和high之間,產生的值是均勻分布的
tf.nn.embedding_lookup(params,ids)是用于查找在params中取出下標為ids的各個項。代碼中的W為各個詞都生成一個向量,tf.nn.embedding_lookup(W,x)想當與只找出文本中有的詞的詞向量。embedding用于詞向量降維。
看到這里,我們可以將得到的詞向量應用在分類模型中。
以下關于模型部分如果覺得難以理解可以不看,畢竟模型可以換。
tf.expand_dims(embedded_chars, -1) 填充維度,是輸入變成卷積網絡輸入格式。
下列代碼部分是拼接幾個卷積池化層結果
pooled_outputs = []
for i, filter_size in enumerate(filter_sizes):
filter_shape = [filter_size, embedding_size, 1, num_filters]
W = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1))
b = tf.Variable(tf.constant(0.1, shape=[num_filters]))
conv = tf.nn.conv2d(embedded_chars, # [batch_size, sequence_length, embedding_size, 1]
W, # [filter_size(n-gram window), embedding_size, 1, num_filters(=3)]
strides=[1, 1, 1, 1],
padding=‘VALID’)
h = tf.nn.relu(tf.nn.bias_add(conv, b))
pooled = tf.nn.max_pool(h,
ksize=[1, sequence_length - filter_size + 1, 1, 1], # [batch_size, filter_height, filter_width, channel]
strides=[1, 1, 1, 1],
padding=‘VALID’)
pooled_outputs.append(pooled) # dim of pooled : [batch_size(=6), output_height(=1), output_width(=1), channel(=1)]
多久沒研究TensorFlow版卷積,參數有些看不懂啦。
第七步:訓練
# Training init = tf.global_variables_initializer() sess = tf.Session() sess.run(init)for epoch in range(5000):_, loss = sess.run([optimizer, cost], feed_dict={X: inputs, Y: outputs})if (epoch + 1)%1000 == 0:print('Epoch:', '%06d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))第八步:預測
如果測試文本比我們訓練集最長文本還要長,要截斷文本。
截斷文本本文代碼未做演示。
這份代碼我是參照的GitHub上,原代碼比這個簡單沒有考慮文本長度不一的情況。
文本分類數據集鏈接:NLP數據集:泰迪杯智慧政務數據集.zip
電氣專業的計算機萌新:余登武。看到這里說明你覺得本文對你有用,請點個贊支持下,謝謝。
總結
以上是生活随笔為你收集整理的word2vec词向量 文本分类实现(TensorFlow版,算法TextCNN)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 姓刘属兔的男孩怎样起名(兔年男孩取名,刘
- 下一篇: 花呗可以分几期