您的位置:首頁>正文

原創|利用TensorFlow對Tweets情感分析

總結:

本文詳細講解了你只需要掌握的TensorFlow的基本知識, 有了這些知識你就能夠學會處理更複雜的問題, 避免了去學習TensorFlow其它基本知識, 畢竟我們的時間有限;講授了多層感知機模型, 在此基礎上你可以繼續擴展成深層網路;詳細講解了詞嵌入的基本知識;本文作為一個全球最頂級大學的lab, 文中開始並未直接給出所有代碼, 而是採用注釋的方式指導你怎樣去一步步的解決問題。 最後, 如果你實在不會寫代碼, 本lab給出了完整代碼, 供你參考。 注:需求完整代碼可以加2290919880。 最後, 尋求最科技前沿感興趣的朋友

教程|深度學習指導——利用TF建立神經網路模型(上)

Tweet情感分析

現在我們處理現實世界的任務。 我們將把tweet的內容分類為積極, 消極或中立三類。 看看下面非常消極的一條tweet:

情感分析模型示意圖

建立模型

建立一個多層感知模型(MLP)

MLP是一個基本的架構, 此架構中我們可以進行矩陣的乘法,

然後添加一些偏置單元, 然後再在每層實現非線性變換。 層與層之間採取全連接的方式, 當網路越深(層數越多), 網路所表達的能力也將呈指數增加。 因為, 神經網路通常能畫出一些漂亮的決策邊界, 而不僅僅是線性邊界。 在本練習中, 你將構建你自己的MLP, 其中使用了2個隱藏層(不包括輸入層和輸出層)。 為了直觀的理解, 給出了一個簡單的MLP, 只有一個隱藏層。

多層感知模型(MLP)

為了使我們我模型訓練更加穩定和高效, 我們將一次評估128條tweets, 並計算出這128條tweets上的損失函數的梯度。 我們稱這種思想叫做小批量訓練。

步驟1:表示單詞

使用詞袋模型乾貨|自然語言處理之詞袋模型表示tweets的內容。 我們的輸出標籤將被表示成一個元素個數為n_classes的向量(本文中n_classes=3)。 我們將通過一些效用函數( utility functions)得到這些資料。

# load data

X, y, index_to_word, sentences = utils.load_sentiment_data_bow()

X_train, y_train, X_test, y_test = utils.split_data(X, y)

vocab_size = X.shape[1]

n_classes = y.shape[1]

print("Tweet:", sentences[5])

print("Label:", y[5])

print("Bag of Words Representation:", X_train[5])

步驟2:設置預留位置(Placeholders)

首先, 我們將資料表示成numpy陣列。 記住:在建立TensorFlow計算圖時, 並沒有輸入實際資料;只有在完整地定義圖後, 我們才提供實際的資料。 我們定義如下的預留位置:

data_placeholder = tf.placeholder(tf.float32, shape=(None, vocab_size), name='data_placeholder')

'''TODO: Make the labels placeholder.''';

labels_placeholder = #todo

為什麼需要傳入參數"None"?

“None”與fluid-sized大小:

你可能注意到data_placeholder()中的shape的第一個維度為“None”。 data_placeholder的shape本應該為(num_tweets, vocab_size), 但是, 我們並不知道我們將要傳入多少tweets, num_tweets是未知的, 可能我們只想一次傳遞1條, 或30條, 或1000條。 幸運的是, TensorFlow允許我們指定fluid-sized大小的預留位置。 我們可以使用None來指定我們shape的一些fluid大小。 當我們的資料最終以numpy陣列的形式輸入時, TensorFlow可以計算出fluid-size的值。

步驟3:定義網路參數

現在讓我們定義和初始化我們的網路參數。

我們使用tf.Variable建立模型參數。 當你創建一個tf.Variable時, 你將傳遞一個tensor到Variable() 中作為它的初始值。 Tensor是一個任意維度N的矩陣。 這裡有許多不同的初始Tensor值函數你可以調用, 這些函數採用list的形式確定其shape。 這裡我們使用tf.truncated_normal作為我們的權重(weights), tf.zeros表示我們的偏差(biases)。

我們將用權重做矩陣乘法運算, 所以前面權重矩陣的最後一個維度必須等於後面與它相乘矩陣的第一個維度。 值得注意的是, 我們可以使用下面的tensor初始化代碼來實現。 最後注意我們的權重張量的size。 我們要預測size=n_classes的向量, 所以我們的神經網路的輸出層需要n_classes個結點。

# Define Network Parameters

# Here, we can define how many units will be in each hidden layer.

n_hidden_units_h0 = 512

n_hidden_units_h1 = 256

# Weights going from input to first hidden layer.

# The first value passed into tf.Variable is initialization of the variable.

# We initialize our weights to be sampled from a truncated normal, as this does something

# called symmetry breaking and keeps the neural network from getting stuck at the start.

# Since the weight matrix multiplies the previous layer to get inputs to the next layer,

# its size is prev_layer_size x next_layer_size.

h0_weights = tf.Variable(tf.truncated_normal([vocab_size, n_hidden_units_h0]),

name='h0_weights')

h0_biases = tf.Variable(tf.zeros([n_hidden_units_h0]),

name='h0_biases')

'''TODO: Set up variables for the weights going into the second hidden layer.

You can check out the tf.Variable API here: https://www.tensorflow.org/api_docs/python/state_ops/variables.

''';

h1_weights = #todo

h1_biases = #todo

# Weights going into the output layer.

out_weights = tf.Variable(

tf.truncated_normal([n_hidden_units_h1, n_classes]),

name='out_weights')

out_biases = tf.Variable(tf.zeros([n_classes]),

name='out_biases')

步驟4:構建計算圖

現在讓我們定義我們的計算圖。

我們計算圖中的第一個操作是tf.matmul。 tf.matmul執行兩個張量(data_placeholder和h0_weights)的矩陣乘法(下圖將有助於你理解), data_placeholder的第1個維度應該等於h0_weights的第0個維度。 然後, 我們添加bias單元h0_bias, 隨後我們使用tf.nn.relu (ReLU)進行非線性變換。 對於下一層, 我們採用同樣的方式, 直到到達最終輸出單元為止。

單層感知器

# Define Computation Graphs

hidden0 = tf.nn.relu(tf.matmul(data_placeholder, h0_weights) + h0_biases)

'''TODO: write the computation to get the output of the second hidden layer.''';

hidden1 = #todo

logits = tf.matmul(hidden1, out_weights) + out_biases

步驟5:定義損失函數

我們已經定義了我們的網路,接下來我們開始訓練我們的網路。訓練網路的基本思想是優化我們的參數使我們的損失函數值最小。然後,我們可以採用梯度下降的方法。

因為我們所做的任務是分類(積極 vs 消極),所以我們常用的損失函數是交叉熵:

交叉熵函數

其中y是我們的預測概率分佈,y'是真實分佈。 我們可以在TensorFlow中使用tf.nn.softmax_cross_entropy_with_logits函數。注意,如果預測結果正確,則該損失函數的值為0。

'''TODO: Define the loss. Use tf.nn.softmax_cross_entropy_with_logits.'''

loss = #todo

learning_rate = 0.0002

# Define the optimizer operation. This is what will take the derivate of the loss

# with respect to each of our parameters and try to minimize it.

optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

prediction = tf.nn.softmax(logits)

# Compute the accuracy

prediction_is_correct = tf.equal(tf.argmax(logits, 1), tf.argmax(labels_placeholder, 1))

accuracy = tf.reduce_mean(tf.cast(prediction_is_correct, tf.float32))

在TensorFlow中,我們要做的一切幾乎都是帶有輸入和輸出的操作。我們的損失變數是一個操作,它能夠接受網路最後一層的輸出,它也能接受網路中從第二層到最後一層的輸出,等等。這就是我們構建的完整計算圖。最後,我們將把損失函數傳遞給我們的優化器(optimizer),優化器能夠計算出相應的梯度,並調劑所有權重參數去最小化損失函數。

步驟6:訓練網路

我們已經定義好了我們的網路,損失函數,也準備好了優化器。現在,我們只需要輸入資料來訓練我們的網路。我們採用批量梯度下降的方法,然後使用反向傳播演算法(BP)。批量梯度下降類似於隨機梯度下降,除開批量梯度下降並不是在每個實例(example)後都更新參數,而是基於在幾個實例後才更新參數。

為了衡量我們的模型的性能,我們不僅只關注模型對訓練集的擬合效果,同時更要關注對模型在測試集上地表現行為。我們可以使用交叉驗證的方法,來提高模型的性能。現在,我們將僅僅使用一個訓練集合測試集。用訓練集來訓練我們的網路,使用測試集評價我們模型的性能。

num_steps = 3000

batch_size = 128

with tf.Session() as session:

# this operation initializes all the variables we made earlier.

tf.global_variables_initializer().run()

for step in range(num_steps):

# Generate a minibatch.

offset = (step * batch_size) % (X_train.shape[0] - batch_size)

batch_data = X_train[offset:(offset + batch_size), :]

batch_labels = y_train[offset:(offset + batch_size), :]

# Create a dictionary to pass in the batch data.

feed_dict_train = {data_placeholder: batch_data, labels_placeholder : batch_labels}

# Run the optimizer, the loss, the predictions.

# We can run multiple things at once and get their outputs.

_, loss_value_train, predictions_value_train, accuracy_value_train = session.run(

[optimizer, loss, prediction, accuracy], feed_dict=feed_dict_train)

# Print stuff every once in a while.

if (step % 100 == 0):

print("Minibatch train loss at step", step, ":", loss_value_train)

print("Minibatch train accuracy: %.3f%%" % (accuracy_value_train*100))

feed_dict_test = {data_placeholder: X_test, labels_placeholder: y_test}

loss_value_test, predictions_value_test, accuracy_value_test = session.run(

[loss, prediction, accuracy], feed_dict=feed_dict_test)

print("Test loss: %.3f" % loss_value_test)

print("Test accuracy: %.3f%%" % (accuracy_value_test*100))

運行以上代碼,你將看到模型的訓練過程,最終模型的準確率達到了65.6%。在下一篇的教程中,我們將展示其方法,提高模型的準確率。

結束的想法

這是對TensorFlow的簡要介紹。 有這麼多,更多的學習和探索,但希望這給了你一些基礎知識來擴大。 作為一個額外的練習,你可以看到你可以用這個代碼來提高性能。 想法包括:隨機化小批量,使網路更深,使用字嵌入(見下文),而不是一袋字,嘗試不同的優化器(如亞當),不同的重量初始化。 我們將在明天探討其中的一些。

這是對TensorFlow的簡要入門介紹,還有更多精彩的內容,需要你自己去學習和探索,但希望這一篇文章能給你讓你掌握基本知識,並以此才促進你進一步的學習。額外的練習:你可以提出一些新的想法來提高模型性能。如隨機化小批量,採用更多的網路層數,使用詞嵌入(見下文),嘗試不同的優化器(如Adam),隨機的權重初始化。

詞嵌入的更多知識

在本次lab中,我們使用了詞袋方法來表示tweet。詞嵌入是一種更好、更有意思的表示方法。基本思想就是用一個向量(vector)表示一個單詞。

我們可以通過訓練神經網路去預測大型訓練集中詞語的語境。然後,神經網路的權重可以被視為一個能捕獲語境的密集的、有用的表示。這是非常強大的,因為我們單詞的表示能捕獲實際的語義相似性。這個詞出現在上下文中。我們通過訓練神經網路來預測大型訓練集中的詞語的上下文。 然後,神經網路的權重可以被認為是捕獲上下文的密集和有用的表示。 這是有用的,因為現在我們的單詞的表示保證實際語義相似性。

詞嵌入能夠捕獲各種有用的語義關係。生成詞嵌入的常用工具是word2vec,你可以參考相關資源。

單層感知器

# Define Computation Graphs

hidden0 = tf.nn.relu(tf.matmul(data_placeholder, h0_weights) + h0_biases)

'''TODO: write the computation to get the output of the second hidden layer.''';

hidden1 = #todo

logits = tf.matmul(hidden1, out_weights) + out_biases

步驟5:定義損失函數

我們已經定義了我們的網路,接下來我們開始訓練我們的網路。訓練網路的基本思想是優化我們的參數使我們的損失函數值最小。然後,我們可以採用梯度下降的方法。

因為我們所做的任務是分類(積極 vs 消極),所以我們常用的損失函數是交叉熵:

交叉熵函數

其中y是我們的預測概率分佈,y'是真實分佈。 我們可以在TensorFlow中使用tf.nn.softmax_cross_entropy_with_logits函數。注意,如果預測結果正確,則該損失函數的值為0。

'''TODO: Define the loss. Use tf.nn.softmax_cross_entropy_with_logits.'''

loss = #todo

learning_rate = 0.0002

# Define the optimizer operation. This is what will take the derivate of the loss

# with respect to each of our parameters and try to minimize it.

optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

prediction = tf.nn.softmax(logits)

# Compute the accuracy

prediction_is_correct = tf.equal(tf.argmax(logits, 1), tf.argmax(labels_placeholder, 1))

accuracy = tf.reduce_mean(tf.cast(prediction_is_correct, tf.float32))

在TensorFlow中,我們要做的一切幾乎都是帶有輸入和輸出的操作。我們的損失變數是一個操作,它能夠接受網路最後一層的輸出,它也能接受網路中從第二層到最後一層的輸出,等等。這就是我們構建的完整計算圖。最後,我們將把損失函數傳遞給我們的優化器(optimizer),優化器能夠計算出相應的梯度,並調劑所有權重參數去最小化損失函數。

步驟6:訓練網路

我們已經定義好了我們的網路,損失函數,也準備好了優化器。現在,我們只需要輸入資料來訓練我們的網路。我們採用批量梯度下降的方法,然後使用反向傳播演算法(BP)。批量梯度下降類似於隨機梯度下降,除開批量梯度下降並不是在每個實例(example)後都更新參數,而是基於在幾個實例後才更新參數。

為了衡量我們的模型的性能,我們不僅只關注模型對訓練集的擬合效果,同時更要關注對模型在測試集上地表現行為。我們可以使用交叉驗證的方法,來提高模型的性能。現在,我們將僅僅使用一個訓練集合測試集。用訓練集來訓練我們的網路,使用測試集評價我們模型的性能。

num_steps = 3000

batch_size = 128

with tf.Session() as session:

# this operation initializes all the variables we made earlier.

tf.global_variables_initializer().run()

for step in range(num_steps):

# Generate a minibatch.

offset = (step * batch_size) % (X_train.shape[0] - batch_size)

batch_data = X_train[offset:(offset + batch_size), :]

batch_labels = y_train[offset:(offset + batch_size), :]

# Create a dictionary to pass in the batch data.

feed_dict_train = {data_placeholder: batch_data, labels_placeholder : batch_labels}

# Run the optimizer, the loss, the predictions.

# We can run multiple things at once and get their outputs.

_, loss_value_train, predictions_value_train, accuracy_value_train = session.run(

[optimizer, loss, prediction, accuracy], feed_dict=feed_dict_train)

# Print stuff every once in a while.

if (step % 100 == 0):

print("Minibatch train loss at step", step, ":", loss_value_train)

print("Minibatch train accuracy: %.3f%%" % (accuracy_value_train*100))

feed_dict_test = {data_placeholder: X_test, labels_placeholder: y_test}

loss_value_test, predictions_value_test, accuracy_value_test = session.run(

[loss, prediction, accuracy], feed_dict=feed_dict_test)

print("Test loss: %.3f" % loss_value_test)

print("Test accuracy: %.3f%%" % (accuracy_value_test*100))

運行以上代碼,你將看到模型的訓練過程,最終模型的準確率達到了65.6%。在下一篇的教程中,我們將展示其方法,提高模型的準確率。

結束的想法

這是對TensorFlow的簡要介紹。 有這麼多,更多的學習和探索,但希望這給了你一些基礎知識來擴大。 作為一個額外的練習,你可以看到你可以用這個代碼來提高性能。 想法包括:隨機化小批量,使網路更深,使用字嵌入(見下文),而不是一袋字,嘗試不同的優化器(如亞當),不同的重量初始化。 我們將在明天探討其中的一些。

這是對TensorFlow的簡要入門介紹,還有更多精彩的內容,需要你自己去學習和探索,但希望這一篇文章能給你讓你掌握基本知識,並以此才促進你進一步的學習。額外的練習:你可以提出一些新的想法來提高模型性能。如隨機化小批量,採用更多的網路層數,使用詞嵌入(見下文),嘗試不同的優化器(如Adam),隨機的權重初始化。

詞嵌入的更多知識

在本次lab中,我們使用了詞袋方法來表示tweet。詞嵌入是一種更好、更有意思的表示方法。基本思想就是用一個向量(vector)表示一個單詞。

我們可以通過訓練神經網路去預測大型訓練集中詞語的語境。然後,神經網路的權重可以被視為一個能捕獲語境的密集的、有用的表示。這是非常強大的,因為我們單詞的表示能捕獲實際的語義相似性。這個詞出現在上下文中。我們通過訓練神經網路來預測大型訓練集中的詞語的上下文。 然後,神經網路的權重可以被認為是捕獲上下文的密集和有用的表示。 這是有用的,因為現在我們的單詞的表示保證實際語義相似性。

詞嵌入能夠捕獲各種有用的語義關係。生成詞嵌入的常用工具是word2vec,你可以參考相關資源。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示