手把手教你用 TensorFlow 实现文本分类(下)
手把手教你用 TensorFlow 實現文本分類(下)
| 本文作者:AI研習社 | 2017-05-29 13:36 |
雷鋒網(公眾號:雷鋒網)按:本文作者張慶恒,原文載于作者個人博客,雷鋒網(公眾號:雷鋒網)已獲授權。
本篇文章主要記錄對之前用神經網絡做文本識別的初步優化,進一步將準確率由原來的65%提高到80%,這里優化的幾個方面包括:
● 隨機打亂訓練數據
● 增加隱層,和驗證集
● 正則化
● 對原數據進行PCA預處理
● 調節訓練參數(迭代次數,batch大小等)
??隨機化訓練數據
觀察訓練數據集,發現訓練集是按類別存儲,讀進內存后在仍然是按類別順序存放。這樣順序取一部分作為驗證集,很大程度上會減少一個類別的訓練樣本數,對該類別的預測準確率會有所下降。所以首先考慮打亂訓練數據。
在已經向量化的訓練數據的基礎上打亂數據,首先合并data和label,打亂后再將數據和標簽分離為trian.txt和train_label.txt。這里可以直接使用shell命令:
1、將labels加到trian.txt的第一列
paste -d" " train_labels.txt train.txt > train_to_shuf.txt
2、隨機打亂文件行
shuf train_to_shuf.txt -o train.txt
3、 提取打亂后文件的第一列,保存到train_labels.txt
cat train.txt | awk '{print $1}' > train_labels.txt
4、刪除第一列label.
awk '{$1="";print $0}' ?train.txt
這樣再次以相同方式訓練,準確率由65%上升到75% 。
??改變網絡結構,增加隱層
之前的網絡直接對輸入數據做softmax回歸,這里考慮增加隱層,數量并加入驗證集觀察準確率的變化情況。這里加入一個隱層,隱層節點數為500,激勵函數使用Relu。替換原來的網絡結構,準確率進一步上升。
??正則化,改善過擬合
觀察模型對訓練集的擬合程度到90%+,而通過上步對訓練數據的準確率為76%,一定程度上出現了過擬合的現象,這里在原有cost function中上加入正則項,希望減輕過擬合的現象。這里使用L2正則。連同上步部分的代碼如下:
#!/usr/bin/python
#-*-coding:utf-8-*-
LAYER_NODE1 = 500 # layer1 node num
INPUT_NODE = 5000
OUTPUT_NODE = 10
REG_RATE = 0.01
import tensorflow as tf
from datasets import datasets
def interface(inputs, w1, b1, w2,b2):
? ? """
? ? ? ? compute forword progration result
? ? """
? ? lay1 = tf.nn.relu(tf.matmul(inputs, w1) + b1)
? ? return tf.nn.softmax(tf.matmul(lay1, w2) + b2) # need softmax??
data_sets = datasets()
data_sets.read_train_data(".", True)
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, [None, INPUT_NODE], name="x-input")
y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name="y-input")
w1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER_NODE1], stddev=0.1))
b1 = tf.Variable(tf.constant(0.0, shape=[LAYER_NODE1]))
w2 = tf.Variable(tf.truncated_normal([LAYER_NODE1, OUTPUT_NODE], stddev=0.1))
b2 = tf.Variable(tf.constant(0.0, shape=[OUTPUT_NODE]))
y = interface(x, w1, b1, w2, b2)
cross_entropy = -tf.reduce_sum(y_ * tf.log(y + 1e-10))
regularizer = tf.contrib.layers.l2_regularizer(REG_RATE)
regularization = regularizer(w1) + regularizer(w2)
loss = cross_entropy + regularization
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
#training
tf.global_variables_initializer().run()
saver = tf.train.Saver()
cv_feed = {x: data_sets.cv.text, y_: data_sets.cv.label}
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
for i in range(5000):
? ? if i % 200 == 0:
? ? ? ? cv_acc = sess.run(acc, feed_dict=cv_feed)
? ? ? ? print "train steps: %d, cv accuracy is %g " % (i, cv_acc)
? ? batch_xs, batch_ys = data_sets.train.next_batch(100)
? ? train_step.run({x: batch_xs, y_: batch_ys})
path = saver.save(sess, "./model4/model.md")
??PCA處理
一方面對文本向量集是嚴重稀疏的矩陣,而且維度較大,一方面影響訓練速度,一方面消耗內存。這里考慮對數據進行PCA處理。該部分希望保存99%的差異率,得到相應的k,即對應的維度。
#!/usr/bin/python
#-*-coding:utf-8-*-
"""
? ? PCA for datasets
"""
import os
import sys
import commands
import numpy
from contextlib import nested
from datasets import datasets
ORIGIN_DIM = 5000
def pca(origin_mat):
? ? """
? ? ? ? gen matrix using pca
? ? ? ? row of origin_mat is one sample of dataset
? ? ? ? col of origin_mat is one feature
? ? ? ? return matrix ?U, s and ?V?
? ? """
? ? # mean,normaliza1on
? ? avg = numpy.mean(origin_mat, axis=0)
? ? # covariance matrix
? ? cov = numpy.cov(origin_mat-avg,rowvar=0)
? ? #Singular Value Decomposition
? ? U, s, V = numpy.linalg.svd(cov, full_matrices=True)
? ? k = 1;
? ? sigma_s = numpy.sum(s)
? ? # chose smallest k for 99% of variance retained?
? ? for k in range(1, ORIGIN_DIM+1):
? ? ? ? variance = numpy.sum(s[0:k]) / sigma_s
? ? ? ? print "k = %d, variance is %f" % (k, variance)
? ? ? ? if variance >= 0.99:
? ? ? ? ? ? break
? ? if k == ORIGIN_DIM:
? ? ? ? print "some thing unexpected , k is same as ORIGIN_DIM"
? ? ? ? exit(1)
? ? return U[:, 0:k], k
if __name__ == '__main__':
? ? """
? ? ? ? main, read train.txt, and do pca
? ? ? ? save file to train_pca.txt
? ? """
? ? data_sets = datasets()
? ? train_text, _ = data_sets.read_from_disk(".", "train", one_hot=False)
? ? U, k = pca(train_text)
? ? print "U shpae: ", U.shape
? ? print "k is : ", k
? ? text_pca = numpy.dot(train_text, U)
? ? text_num = text_pca.shape[0]
? ? print "text_num in pca is ", text_num
? ? with open("./train_pca.txt", "a+") as f:
? ? ? ? for i in range(0, text_num):
? ? ? ? ? ? f.write(" ".join(map(str, text_pca[i,:])) + "\n")
最終得到k=2583。該部分準確率有所提高但影響不大。
??調整網絡參數
該部分主要根據嚴重集和測試集的表現不斷調整網路參數,包括學習率、網路層數、每層節點個數、正則損失、迭代次數、batch大小等。最終得到80%的準確率。
??小結
對神經網路進行初步優化,由原來的65%的準確率提高到80%,主要的提高在于訓練數據的隨機化,以及網絡結構的調整。為提升訓練速度,同時減少內存消耗,對數據進行了降維操作。
之后對代碼的結構進行了整理,這里沒有提及,該部分代碼包括?nn_interface.py?和?nn_train.py?分別實現對網絡結構的定義以及訓練流程的管理。
后面會結合tensorflow的使用技巧對訓練進行進一步優化。
雷鋒網相關文章:
手把手教你用 TensorFlow 實現文本分類(上)
手把手教你如何用 TensorFlow 實現基于 DNN 的文本分類
總結
以上是生活随笔為你收集整理的手把手教你用 TensorFlow 实现文本分类(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GMIS 2017大会邓力演讲:无监督学
- 下一篇: 谷歌I/O走进TensorFlow开源模