利用TensorFlow和神经网络来处理文本分类问题

By 机器之心2017年8月23日 10:33

在这篇文章中,机器之心海外分析师对Medium(链接见文后)上的一篇热门博客进行了介绍,讨论了六个关于创建机器学习模型来进行文本分类的主要话题。

在这篇文章中,作者讨论了六个关于创建机器学习模型来进行文本分类的主要话题。

  1. TensorFlow 如何工作
  2. 机器学习模型是什么
  3. 神经网络是什么
  4. 神经网络怎样进行学习
  5. 如何处理数据并且把它们传输给神经网络的输入
  6. 怎样运行模型并且得到预测结果

作者也提供了可在Jupyter notebook上运行的代码。我将回顾这六个话题并且与我自己的经验相结合。

1. TensorFlow 概览

TensorFlow 是最流行的开源 AI 库之一。它的高计算效率,丰富的开发资源使它被企业和个人开发者广泛采用。在我看来,学习 TensorFlow 的最好的方法就是使用它的官网教程(https://www.tensorflow.org/)。在这个网站上,你可以浏览「getting started」教程。

我首先将会对 TensorFlow 的基本定义和主要特征进行介绍。张量(Tensor)是一种数据结构,它可以把原始值形成任意的多维数组【1】。张量的级别就是它的维度数。这里,我建议阅读 Python 的应用编程接口 API,因为它对 TensorFlow 的初学者来说是很友好的。你可以安装 TensorFlow 并且配置环境,紧随官方网站上的指导就可以了。测试你是否成功安装 TensorFlow 的方法就是导入(import)TensorFlow 库。在 TensorFlow 中,计算图(computational graph)是核心部件。数据流程图形用来代表计算过程。在图形下,操作(Operation)代表计算单位,张量代表数据单位。为了运行代码,我们应该对阶段函数(Session function)进行初始化。这里是执行求和操作的完整代码。

#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 中编译是遵循一种模式的,并且很容易被记住。你将会导入库,创建恒定张量(constant tensors)并且创建图形。然后我们应该定义哪一个图将会被在 Session 中使用,并且定义操作单元。最终你可以在 Session 中使用 run() 的方法,并且评估其中参数获取的每一个张量。

2. 预测模型

预测模型可以很简单。它把机器学习算法和数据集相结合。创建一个模型的过程程如下图所示:

我们首先应该找到正确的数据作为输入,并且使用一些数据处理函数来处理数据。然后,这些数据就可以与机器学习算法结合来创建模型了。在你得到模型后,你可以把模型当做一个预测器并且输入需要的数据来预测,从而产生结果。整个进程如下图所示:

在本文中,输入是文本,输出结果是类别(category)。这种机器学习算法叫做监督学习,训练数据集是已标注过种类的文本。这也是分类任务,而且是应用神经网络来进行模型创建的。

3. 神经网络

神经网络的主要特征是自学(self-learning),而不是进行明确地程序化。它的灵感来源于人类中枢神经系统。第一个神经网络算法是感知机(Perceptron)。

为了理解神经网络的工作机制,作者用 TensorFlow 创建了一个神经网络结构。

神经网络结构

这里作者使用了两个隐蔽层(hidden layers),每一个隐蔽层的职责是把输入转换成输出层可以使用的东西【1】。第一个隐蔽层的节点的数量应该被定义。这些节点叫做神经元,和权值相乘。训练阶段是为了对这些值进行调节,为了产生一个正确的输出。网络也引入了偏差(bias),这就可以让你向左或向右移动激活函数,从而让预测结果更加准确【2】。数据还会经过一个定义每个神经元最终输出的激活函数。这里,作者使用的是修正线性单元(ReLU),可以增加非线性。这个函数被定义为:

f(x) = max(0,x)(输出是 x 或 0,无论 x 多大)

对第二个隐蔽层来说,输入就是第一层,函数与第一个隐蔽层相同。

对于输出层,作者使用的是 one-hot 编码来得到结果。在 one-hot 编码中,除了其中的一位值为 1 以外,所有的位元(bits)都会得到一个 0 值。这里使用三种类别作为范例,如下图所示。

我们可以发现输出节点的数量值就是类别的数量值。如果我们想要划分不同的类别,我们可以使用 Softmax 函数来使每一个单元的输出转化成 0 到 1 间的值,并且使所有单元的总和为 1。它将会告诉我们每种类别的概率是多少。

上述过程由下列代码实现:

# Network Parameters
n_hidden_1 = 10        # 1st layer number of features
n_hidden_2 = 5         # 2nd layer number of features
n_input = total_words  # Words in vocab
n_classes = 3          # Categories: graphics, space and baseball
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_activation = tf.nn.relu(layer_1_addition)
# Hidden layer with RELU activationlayer_2_multiplication = tf.matmul(layer_1_activation, weights['h2'])layer_2_addition = tf.add(layer_2_multiplication, biases['b2'])layer_2_activation = tf.nn.relu(layer_2_addition)
# Output layer with linear activationout_layer_multiplication = tf.matmul(layer_2_activation, weights['out'])out_layer_addition = out_layer_multiplication + biases['out']
return out_layer_addition

在这里,它调用了 matmul()函数来实现矩阵之间的乘法函数,并调用 add()函数将偏差添加到函数中。

4. 神经网络是如何训练的

我们可以看到其中要点是构建一个合理的结构,并优化网络权重的预测。接下来我们需要训练 TensorFlow 中的神经网络。在 TensorFlow 中,我们使用 Variable 来存储权重和偏差。在这里,我们应该将输出值与预期值进行比较,并指导函数获得最小损失结果。有很多方法来计算损失函数,由于它是一个分类任务,所以我们应该使用交叉熵误差。此前 D. McCaffrey[3] 分析并认为交叉熵可以避免训练停滞不前。我们在这里通过调用函数 tf.nn.softmax_cross_entropy_with_logits() 来使用交叉熵误差,我们还将通过调用 function: tf.reduced_mean() 来计算误差。

# Construct model
prediction = multilayer_perceptron(input_tensor, weights, biases)
# Define loss
entropy_loss = tf.nn.softmax_cross_entropy_with_logits(logits=prediction, labels=output_tensor)
loss = tf.reduce_mean(entropy_loss)

我们应该找到最优值来使输出误差最小化。这里我们使用随机梯度下降(SGD)的方法:

通过多次迭代,我们将会得到接近于全局最小损失的权值。学习速率不应该太大。自适应瞬间评估函数(Adaptive Moment Estimation function)经常用于计算梯度下降。在这个优化算法中,对梯度和梯度的二阶矩量进行平滑处理【4】。

代码如下所示,在其它项目中,学习速率可以是动态的,从而使训练过程更加迅速。

learning_rate = 0.001
# Construct model
prediction = multilayer_perceptron(input_tensor, weights, biases)
# Define loss
entropy_loss = tf.nn.softmax_cross_entropy_with_logits(logits=prediction, labels=output_tensor)
loss = tf.reduce_mean(entropy_loss)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)

5. 数据操作

这一部分对于分类成功也很重要。机器学习的开发者们需要更加在意数据,这会为你节省大量时间,并让结果更加准确,因为这可以让你无需从头开始更改配置。在这里,笔者需要指出两个重点。首先,为每个单词创建一个索引;然后为每个文本创建一个矩阵,如果单词在文本中,则值为 1,否则为 0。以下代码可以帮助你理解这个过程:

import numpy as np    #numpy is a package for scientific computing
from collections import Counter
vocab = Counter()
text = "Hi from Brazil"
#Get all words
for word in text.split(' '):vocab[word]+=1#Convert words to indexes
def get_word_2_index(vocab):word2index = {}for i,word in enumerate(vocab):word2index[word] = ireturn word2index
#Now we have an index
word2index = get_word_2_index(vocab)
total_words = len(vocab)
#This is how we create a numpy array (our matrix)
matrix = np.zeros((total_words),dtype=float)
#Now we fill the values
for word in text.split():matrix[word2index[word]] += 1
print(matrix)
>>> [ 1.  1.  1.]

Python 中的 Counter() 是一个哈希表。当输入是「Hi from Brazil」时,矩阵是 [1 ,1, 1]。如果输入不同,比如「Hi」,矩阵会得到不同的结果:

matrix = np.zeros((total_words),dtype=float)
text = "Hi"
for word in text.split():matrix[word2index[word.lower()]] += 1
print(matrix)
>>> [ 1.  0.  0.]

6. 运行模型,获得结果

在这一部分里,我们将使用 20 Newsgroups 作为数据集。它包含有关 20 种话题的 18,000 篇文章。我们使用 scilit-learn 库加载数据。在这里作者使用了 3 个类别:comp.graphics、sci.space 和 rec.sport.baseball。它有两个子集,一个用于训练,一个用于测试。下面是加载数据集的方式:

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)

它遵循通用的模式,非常易于开发者使用。

在实验中,epoch 设定为 10,这意味着会有 10 次正+反向遍历整个数据集。在 TensorFlow 中,占位符的作用是用作 Feed 的目标,用于传递每个运行步骤的数据。

n_input = total_words # Words in vocab
n_classes = 3         # Categories: graphics, sci.space and baseball
input_tensor = tf.placeholder(tf.float32,[None, n_input],name="input")
output_tensor = tf.placeholder(tf.float32,[None, n_classes],name="output")

我们应该分批训练数据,因为在测试模型时,我们会用更大的批次来输入 dict。调用 get_batches() 函数来获取具有批处理尺寸的文本数。接下来,我们就可以运行模型了。

training_epochs = 10
# Launch the graph
with tf.Session() as sess:sess.run(init) #inits the variables (normal distribution, remember?)# 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})

在这里我们需要构建测试模型,并计算它的准确性。

    # Test modelindex_prediction = tf.argmax(prediction, 1)index_correct = tf.argmax(output_tensor, 1)correct_prediction = tf.equal(index_prediction, index_correct)# 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}))

然后我们就可以得到结果:

结论

本文介绍了如何使用神经网络和 TensorFlow 来处理文本分类任务。它介绍了与实验有关的基础信息,然而,在我自己运行的时候,效果就没有作者那么好了。我们或许可以在这个架构的基础上改进一番,在隐藏层中使用 dropout 肯定会提高准确性。

在运行代码前,请确认你已安装了最新版本的 TensorFlow。有些时候你可能会无法导入 twenty_newsgroups 数据集。当这种情况发生时,请使用以下代码来解决问题。

# 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()

以下是完整代码:

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}))

参考内容:

[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

利用TensorFlow和神经网络来处理文本分类问题相关推荐

  1. Tensorflow使用CNN卷积神经网络以及RNN(Lstm、Gru)循环神经网络进行中文文本分类

    Tensorflow使用CNN卷积神经网络以及RNN(Lstm.Gru)循环神经网络进行中文文本分类 本案例采用清华大学NLP组提供的THUCNews新闻文本分类数据集的一个子集进行训练和测试http ...

  2. TensorFlow使用CNN实现中文文本分类

    TensorFlow使用CNN实现中文文本分类 读研期间使用过TensorFlow实现过简单的CNN情感分析(分类),当然这是比较low的二分类情况,后来进行多分类情况.但之前的学习基本上都是在英文词 ...

  3. Tensorflow使用LSTM实现中文文本分类(1)

    前言 使用Tensorflow,利用LSTM进行中文文本的分类. 数据集格式如下: ''' 体育 马晓旭意外受伤让国奥警惕 无奈大雨格外青睐殷家军记者傅亚雨沈阳报道 来到沈阳,国奥队依然没有摆脱雨水的 ...

  4. Tensorflow使用Char-CNN实现中文文本分类(1)

    前言 在之前的中文文本分类中,使用了LSTM来进行模型的构建(详情参考: Tensorflow使用LSTM实现中文文本分类(2).使用numpy实现LSTM和RNN网络的前向传播过程).除了使用LST ...

  5. [Pytorch系列-61]:循环神经网络 - 中文新闻文本分类详解-3-CNN网络训练与评估代码详解

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...

  6. [Pytorch系列-60]:循环神经网络 - 中文新闻文本分类详解-2-LSTM网络训练与评估代码详解

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...

  7. 文本分类(下) | 卷积神经网络(CNN)在文本分类上的应用

    正文共3758张图,4张图,预计阅读时间18分钟. 1.简介 原先写过两篇文章,分别介绍了传统机器学习方法在文本分类上的应用以及CNN原理,然后本篇文章结合两篇论文展开,主要讲述下CNN在文本分类上的 ...

  8. 手把手教你如何用 TensorFlow 实现基于 DNN 的文本分类

    许多开发者向新手建议:如果你想要入门机器学习,就必须先了解一些关键算法的工作原理,然后再开始动手实践.但我不这么认为. 我觉得实践高于理论,新手首先要做的是了解整个模型的工作流程,数据大致是怎样流动的 ...

  9. TensorFlow – 使用CNN进行中文文本分类

    使用卷积神经网络(CNN)处理自然语言处理(NLP)中的文本分类问题.本文将结合TensorFlow代码介绍: 词嵌入 填充 Embedding 卷积层 卷积(tf.nn.conv1d) 池化(poo ...

最新文章

  1. 【Leetcode】刷题的开始
  2. bzoj1492: [NOI2007]货币兑换Cash
  3. 人生三部曲:顺序,选择,循环
  4. Java 虚拟机经典六问
  5. 10-线程,进程,协程,IO多路复用
  6. Deepin 15.7安装教程
  7. 嵌入式开发中,用C++真香!
  8. JAVA并发篇_公平锁与非公平锁
  9. 面试官最爱的 volatile 关键字,这些问题你都搞懂了没?
  10. python怎么创建变量_Python中通过函数对象创建全局变量
  11. JavaScript学习(四十二)—利用工厂模式创建对象以及工厂模式创建对象的不足
  12. Centos6.5不支持ip nets命令
  13. python 读取并显示图片,用plt 同时显示多幅图像
  14. web开发兼容性测试工具
  15. socket中的recv函数
  16. 要想Essay写得好,切记要警惕这六大禁区
  17. 9:JDBC-Java API 实战
  18. OD使用经验【转载】
  19. linux编译openssl报错,cargo编译musl报错openssl
  20. 5G通信光模块是什么?5G通信光模块的发展方向如何?

热门文章

  1. C++中前置操作符和后置操作符的重载
  2. python 可视化_Python可视化|Matplotlib40LaTeX in Matplotlib和python
  3. linux体验服务器,体验Ubuntu做服务器
  4. 深圳大学计算机英语作业答案,2016年深圳大学大学计算机基础mooc课第四章答案...
  5. 《基于张量网络的机器学习入门》学习笔记5
  6. 如何用python画一个小房子?
  7. Python判断 子集
  8. 对比学习系列论文SDCLR(一)-Self-Damaging Contrastive Learning论文的概括
  9. 机器学习笔记:高斯过程
  10. python 文件处理1:将某一目录下的文件合并