利用TensorFlow和神经网络来处理文本分类问题
利用TensorFlow和神經(jīng)網(wǎng)絡(luò)來處理文本分類問題
By?機(jī)器之心2017年8月23日 10:33 在這篇文章中,機(jī)器之心海外分析師對Medium(鏈接見文后)上的一篇熱門博客進(jìn)行了介紹,討論了六個關(guān)于創(chuàng)建機(jī)器學(xué)習(xí)模型來進(jìn)行文本分類的主要話題。
在這篇文章中,作者討論了六個關(guān)于創(chuàng)建機(jī)器學(xué)習(xí)模型來進(jìn)行文本分類的主要話題。
作者也提供了可在Jupyter notebook上運(yùn)行的代碼。我將回顧這六個話題并且與我自己的經(jīng)驗相結(jié)合。
1. TensorFlow 概覽
TensorFlow 是最流行的開源 AI 庫之一。它的高計算效率,豐富的開發(fā)資源使它被企業(yè)和個人開發(fā)者廣泛采用。在我看來,學(xué)習(xí) TensorFlow 的最好的方法就是使用它的官網(wǎng)教程(https://www.tensorflow.org/)。在這個網(wǎng)站上,你可以瀏覽「getting started」教程。
我首先將會對 TensorFlow 的基本定義和主要特征進(jìn)行介紹。張量(Tensor)是一種數(shù)據(jù)結(jié)構(gòu),它可以把原始值形成任意的多維數(shù)組【1】。張量的級別就是它的維度數(shù)。這里,我建議閱讀 Python 的應(yīng)用編程接口 API,因為它對 TensorFlow 的初學(xué)者來說是很友好的。你可以安裝 TensorFlow 并且配置環(huán)境,緊隨官方網(wǎng)站上的指導(dǎo)就可以了。測試你是否成功安裝 TensorFlow 的方法就是導(dǎo)入(import)TensorFlow 庫。在 TensorFlow 中,計算圖(computational graph)是核心部件。數(shù)據(jù)流程圖形用來代表計算過程。在圖形下,操作(Operation)代表計算單位,張量代表數(shù)據(jù)單位。為了運(yùn)行代碼,我們應(yīng)該對階段函數(shù)(Session function)進(jìn)行初始化。這里是執(zhí)行求和操作的完整代碼。
#import the library import tensorflow as tf #build the graph and name as my_graph my_graph = tf.Graph() #tf.Session encapsulate the environment for my_graph with my_graph.as_default():x = tf.constant([1,3,6]) y = tf.constant([1,1,1])#add functionop = tf.add(x,y)#run it by fetchesresult = sess.run(fetches=op)#print itprint(result)你可以看見在 TensorFlow 中編譯是遵循一種模式的,并且很容易被記住。你將會導(dǎo)入庫,創(chuàng)建恒定張量(constant tensors)并且創(chuàng)建圖形。然后我們應(yīng)該定義哪一個圖將會被在 Session 中使用,并且定義操作單元。最終你可以在 Session 中使用 run() 的方法,并且評估其中參數(shù)獲取的每一個張量。
2. 預(yù)測模型
預(yù)測模型可以很簡單。它把機(jī)器學(xué)習(xí)算法和數(shù)據(jù)集相結(jié)合。創(chuàng)建一個模型的過程程如下圖所示:
我們首先應(yīng)該找到正確的數(shù)據(jù)作為輸入,并且使用一些數(shù)據(jù)處理函數(shù)來處理數(shù)據(jù)。然后,這些數(shù)據(jù)就可以與機(jī)器學(xué)習(xí)算法結(jié)合來創(chuàng)建模型了。在你得到模型后,你可以把模型當(dāng)做一個預(yù)測器并且輸入需要的數(shù)據(jù)來預(yù)測,從而產(chǎn)生結(jié)果。整個進(jìn)程如下圖所示:
在本文中,輸入是文本,輸出結(jié)果是類別(category)。這種機(jī)器學(xué)習(xí)算法叫做監(jiān)督學(xué)習(xí),訓(xùn)練數(shù)據(jù)集是已標(biāo)注過種類的文本。這也是分類任務(wù),而且是應(yīng)用神經(jīng)網(wǎng)絡(luò)來進(jìn)行模型創(chuàng)建的。
3. 神經(jīng)網(wǎng)絡(luò)
神經(jīng)網(wǎng)絡(luò)的主要特征是自學(xué)(self-learning),而不是進(jìn)行明確地程序化。它的靈感來源于人類中樞神經(jīng)系統(tǒng)。第一個神經(jīng)網(wǎng)絡(luò)算法是感知機(jī)(Perceptron)。
為了理解神經(jīng)網(wǎng)絡(luò)的工作機(jī)制,作者用 TensorFlow 創(chuàng)建了一個神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。
神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
這里作者使用了兩個隱蔽層(hidden layers),每一個隱蔽層的職責(zé)是把輸入轉(zhuǎn)換成輸出層可以使用的東西【1】。第一個隱蔽層的節(jié)點(diǎn)的數(shù)量應(yīng)該被定義。這些節(jié)點(diǎn)叫做神經(jīng)元,和權(quán)值相乘。訓(xùn)練階段是為了對這些值進(jìn)行調(diào)節(jié),為了產(chǎn)生一個正確的輸出。網(wǎng)絡(luò)也引入了偏差(bias),這就可以讓你向左或向右移動激活函數(shù),從而讓預(yù)測結(jié)果更加準(zhǔn)確【2】。數(shù)據(jù)還會經(jīng)過一個定義每個神經(jīng)元最終輸出的激活函數(shù)。這里,作者使用的是修正線性單元(ReLU),可以增加非線性。這個函數(shù)被定義為:
對第二個隱蔽層來說,輸入就是第一層,函數(shù)與第一個隱蔽層相同。
對于輸出層,作者使用的是 one-hot 編碼來得到結(jié)果。在 one-hot 編碼中,除了其中的一位值為 1 以外,所有的位元(bits)都會得到一個 0 值。這里使用三種類別作為范例,如下圖所示。
我們可以發(fā)現(xiàn)輸出節(jié)點(diǎn)的數(shù)量值就是類別的數(shù)量值。如果我們想要劃分不同的類別,我們可以使用 Softmax 函數(shù)來使每一個單元的輸出轉(zhuǎn)化成 0 到 1 間的值,并且使所有單元的總和為 1。它將會告訴我們每種類別的概率是多少。
上述過程由下列代碼實(shí)現(xiàn):
在這里,它調(diào)用了 matmul()函數(shù)來實(shí)現(xiàn)矩陣之間的乘法函數(shù),并調(diào)用 add()函數(shù)將偏差添加到函數(shù)中。
4. 神經(jīng)網(wǎng)絡(luò)是如何訓(xùn)練的
我們可以看到其中要點(diǎn)是構(gòu)建一個合理的結(jié)構(gòu),并優(yōu)化網(wǎng)絡(luò)權(quán)重的預(yù)測。接下來我們需要訓(xùn)練 TensorFlow 中的神經(jīng)網(wǎng)絡(luò)。在 TensorFlow 中,我們使用 Variable 來存儲權(quán)重和偏差。在這里,我們應(yīng)該將輸出值與預(yù)期值進(jìn)行比較,并指導(dǎo)函數(shù)獲得最小損失結(jié)果。有很多方法來計算損失函數(shù),由于它是一個分類任務(wù),所以我們應(yīng)該使用交叉熵誤差。此前 D. McCaffrey[3] 分析并認(rèn)為交叉熵可以避免訓(xùn)練停滯不前。我們在這里通過調(diào)用函數(shù) tf.nn.softmax_cross_entropy_with_logits() 來使用交叉熵誤差,我們還將通過調(diào)用 function: tf.reduced_mean() 來計算誤差。
我們應(yīng)該找到最優(yōu)值來使輸出誤差最小化。這里我們使用隨機(jī)梯度下降(SGD)的方法:
通過多次迭代,我們將會得到接近于全局最小損失的權(quán)值。學(xué)習(xí)速率不應(yīng)該太大。自適應(yīng)瞬間評估函數(shù)(Adaptive Moment Estimation function)經(jīng)常用于計算梯度下降。在這個優(yōu)化算法中,對梯度和梯度的二階矩量進(jìn)行平滑處理【4】。
代碼如下所示,在其它項目中,學(xué)習(xí)速率可以是動態(tài)的,從而使訓(xùn)練過程更加迅速。
5. 數(shù)據(jù)操作
這一部分對于分類成功也很重要。機(jī)器學(xué)習(xí)的開發(fā)者們需要更加在意數(shù)據(jù),這會為你節(jié)省大量時間,并讓結(jié)果更加準(zhǔn)確,因為這可以讓你無需從頭開始更改配置。在這里,筆者需要指出兩個重點(diǎn)。首先,為每個單詞創(chuàng)建一個索引;然后為每個文本創(chuàng)建一個矩陣,如果單詞在文本中,則值為 1,否則為 0。以下代碼可以幫助你理解這個過程:
Python 中的 Counter() 是一個哈希表。當(dāng)輸入是「Hi from Brazil」時,矩陣是 [1 ,1, 1]。如果輸入不同,比如「Hi」,矩陣會得到不同的結(jié)果:
6. 運(yùn)行模型,獲得結(jié)果
在這一部分里,我們將使用 20 Newsgroups 作為數(shù)據(jù)集。它包含有關(guān) 20 種話題的 18,000 篇文章。我們使用 scilit-learn 庫加載數(shù)據(jù)。在這里作者使用了 3 個類別:comp.graphics、sci.space 和 rec.sport.baseball。它有兩個子集,一個用于訓(xùn)練,一個用于測試。下面是加載數(shù)據(jù)集的方式:
from sklearn.datasets import fetch_20newsgroups categories = ["comp.graphics","sci.space","rec.sport.baseball"] newsgroups_train = fetch_20newsgroups(subset='train', categories=categories) newsgroups_test = fetch_20newsgroups(subset='test', categories=categories)它遵循通用的模式,非常易于開發(fā)者使用。
在實(shí)驗中,epoch 設(shè)定為 10,這意味著會有 10 次正+反向遍歷整個數(shù)據(jù)集。在 TensorFlow 中,占位符的作用是用作 Feed 的目標(biāo),用于傳遞每個運(yùn)行步驟的數(shù)據(jù)。
我們應(yīng)該分批訓(xùn)練數(shù)據(jù),因為在測試模型時,我們會用更大的批次來輸入 dict。調(diào)用 get_batches() 函數(shù)來獲取具有批處理尺寸的文本數(shù)。接下來,我們就可以運(yùn)行模型了。
在這里我們需要構(gòu)建測試模型,并計算它的準(zhǔn)確性。
然后我們就可以得到結(jié)果:
結(jié)論
本文介紹了如何使用神經(jīng)網(wǎng)絡(luò)和 TensorFlow 來處理文本分類任務(wù)。它介紹了與實(shí)驗有關(guān)的基礎(chǔ)信息,然而,在我自己運(yùn)行的時候,效果就沒有作者那么好了。我們或許可以在這個架構(gòu)的基礎(chǔ)上改進(jìn)一番,在隱藏層中使用 dropout 肯定會提高準(zhǔn)確性。
在運(yùn)行代碼前,請確認(rèn)你已安裝了最新版本的 TensorFlow。有些時候你可能會無法導(dǎo)入 twenty_newsgroups 數(shù)據(jù)集。當(dāng)這種情況發(fā)生時,請使用以下代碼來解決問題。
以下是完整代碼:
import pandas as pd import numpy as np import tensorflow as tf from collections import Counter from sklearn.datasets import fetch_20newsgroups # if you didn't download the twenty_newsgroups datasets, it will run with error # this logging can help to solve the error import logging logging.basicConfig()categories = ["comp.graphics","sci.space","rec.sport.baseball"] newsgroups_train = fetch_20newsgroups(subset='train', categories=categories) newsgroups_test = fetch_20newsgroups(subset='test', categories=categories)print('total texts in train:',len(newsgroups_train.data)) print('total texts in test:',len(newsgroups_test.data))vocab = Counter() for text in newsgroups_train.data:for word in text.split(' '):vocab[word.lower()]+=1for text in newsgroups_test.data:for word in text.split(' '):vocab[word.lower()]+=1total_words = len(vocab) def get_word_2_index(vocab):word2index = {}for i,word in enumerate(vocab):word2index[word.lower()] = ireturn word2indexword2index = get_word_2_index(vocab)def get_batch(df,i,batch_size):batches = []results = []texts = df.data[i*batch_size:i*batch_size+batch_size]categories = df.target[i*batch_size:i*batch_size+batch_size]for text in texts:layer = np.zeros(total_words,dtype=float)for word in text.split(' '):layer[word2index[word.lower()]] += 1batches.append(layer)for category in categories:y = np.zeros((3),dtype=float)if category == 0:y[0] = 1.elif category == 1:y[1] = 1.else:y[2] = 1.results.append(y)return np.array(batches),np.array(results)# Parameters learning_rate = 0.01 training_epochs = 10 batch_size = 150 display_step = 1# Network Parameters n_hidden_1 = 100 # 1st layer number of features n_hidden_2 = 100 # 2nd layer number of features n_input = total_words # Words in vocab n_classes = 3 # Categories: graphics, sci.space and baseballinput_tensor = tf.placeholder(tf.float32,[None, n_input],name="input") output_tensor = tf.placeholder(tf.float32,[None, n_classes],name="output") def multilayer_perceptron(input_tensor, weights, biases):layer_1_multiplication = tf.matmul(input_tensor, weights['h1'])layer_1_addition = tf.add(layer_1_multiplication, biases['b1'])layer_1 = tf.nn.relu(layer_1_addition)# Hidden layer with RELU activationlayer_2_multiplication = tf.matmul(layer_1, weights['h2'])layer_2_addition = tf.add(layer_2_multiplication, biases['b2'])layer_2 = tf.nn.relu(layer_2_addition)# Output layer out_layer_multiplication = tf.matmul(layer_2, weights['out'])out_layer_addition = out_layer_multiplication + biases['out']return out_layer_addition# Store layers weight & bias weights = {'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes])) } biases = {'b1': tf.Variable(tf.random_normal([n_hidden_1])),'b2': tf.Variable(tf.random_normal([n_hidden_2])),'out': tf.Variable(tf.random_normal([n_classes])) }# Construct model prediction = multilayer_perceptron(input_tensor, weights, biases)# Define loss and optimizer loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=prediction, labels=output_tensor)) optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)# Initializing the variables init = tf.initialize_all_variables()# Launch the graph with tf.Session() as sess:sess.run(init)# Training cyclefor epoch in range(training_epochs):avg_cost = 0.total_batch = int(len(newsgroups_train.data)/batch_size)# Loop over all batchesfor i in range(total_batch):batch_x,batch_y = get_batch(newsgroups_train,i,batch_size)# Run optimization op (backprop) and cost op (to get loss value)c,_ = sess.run([loss,optimizer], feed_dict={input_tensor: batch_x,output_tensor:batch_y})# Compute average lossavg_cost += c / total_batch# Display logs per epoch stepif epoch % display_step == 0:print("Epoch:", '%04d' % (epoch+1), "loss=", \"{:.9f}".format(avg_cost))print("Optimization Finished!")# Test modelcorrect_prediction = tf.equal(tf.argmax(prediction, 1), tf.argmax(output_tensor, 1))# Calculate accuracyaccuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))total_test_data = len(newsgroups_test.target)batch_x_test,batch_y_test = get_batch(newsgroups_test,0,total_test_data)print("Accuracy:", accuracy.eval({input_tensor: batch_x_test, output_tensor: batch_y_test}))參考內(nèi)容:
[1] https://stats.stackexchange.com/questions/63152/what-does-the-hidden-layer-in-a-neural-network-compute
[2] http://stackoverflow.com/questions/2480650/role-of-bias-in-neural-networks
[3] https://jamesmccaffrey.wordpress.com/2013/11/05/why-you-should-use-cross-entropy-error-instead-of-classification-error-or-mean-squared-error-for-neural-network-classifier-training/
[4] https://en.wikipedia.org/wiki/Stochastic_gradient_descent
Medium 文章鏈接:https://medium.freecodecamp.org/big-picture-machine-learning-classifying-text-with-neural-networks-and-tensorflow-d94036ac2274
?
總結(jié)
以上是生活随笔為你收集整理的利用TensorFlow和神经网络来处理文本分类问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习在情感分析中的应用
- 下一篇: 技术有时间衰减因子.