机器学习的大局:用神经网络和TensorFlow分类文本

本译文自Déborah Mesquitahttps://medium.freecodecamp.org发表的Big Picture Machine Learning: Classifying Text with Neural Networks and TensorFlow ,文中版权、图像代码等数据均归作者所有。为了本土化,翻译内容略作修改。

开发人员常说,如果你想开始机器学习,你应该先学习算法是如何工作的。但是我的经验表明并不是这样子。

我说你应该首先能够看到大局:应用程序是如何工作的。一旦你了解了这一点,深入探索和研究算法的内部工作变得更加容易。

那么,你如何发展一种直觉,并对机器学习有一个全面的了解呢?一个好的方法是创建机器学习模型

假设你还不知道如何从头开始创建所有这些算法,那么你就需要使用一个已经为你实现了所有这些算法的库。那个库就是TensorFlow

在本文中,我们将创建一个机器学习模型来将文本分类。我们将介绍以下主题:

  1. TensorFlow如何工作
  2. 什么是机器学习模型
  3. 什么是神经网络?
  4. 神经网络如何学习
  5. 如何处理数据并将其传递给神经网络输入
  6. 如何运行模型并获得预测结果

你可能会学到很多新东西,所以我们开始吧!

TensorFlow

TensorFlow是一个开源的机器学习库,最初由Google创建。图书馆的名字帮助我们理解我们如何使用它:张量是多维数组,流过图的节点。

tf.Graph

TensorFlow中的每个计算都被表示为一个数据流图。这个图有两个元素:

  • 一组tf.Operation代表计算单位
  • 一组tf.Tensor代表数据的单位

要看到所有这些工作,你将创建这个数据流图:

一个计算x + y的图

你会定义x = [1,3,6]y = [1,1,1]。如图所示tf.Tensor,您可以创建常量张量:

import tensorflow as tf
x = tf.constant([1,3,6])
y = tf.constant([1,1,1])

现在您将定义操作单元:

import tensorflow as tf
x = tf.constant([1,3,6])
y = tf.constant([1,1,1])
op = tf.add(x,y)

你有所有的图形元素。现在你需要建立图表:

import tensorflow as tf
my_graph = tf.Graph()
with my_graph.as_default():
     x = tf.constant([1,3,6])
    y = tf.constant([1,1,1])
    op = tf.add(x,y)

这就是TensorFlow工作流程的工作原理:您首先创建一个图表,然后才能进行计算(真正“运行”具有操作的图形节点)。要运行图形,你需要创建一个tf.Session

tf.Session

一个tf.Session对象封装了Operation执行对象的环境,并对Tensor对象进行了评估(来自文档)。为此,我们需要定义在会话中使用哪个图表:

import tensorflow as tf
my_graph = tf.Graph()
用tf.Session(graph = my_graph)作为sess:
    x = tf.constant([1,3,6])
    y = tf.constant([1,1,1])
    op = tf.add(x,y)

要执行操作,您将使用该方法tf.Session.run()。该方法执行TensorFlow计算的一个“步骤”,通过运行必要的图片段来执行每个Operation对象并评估每个Tensor传入的参数fetches。在你的情况下,你将运行总和操作的一个步骤:

import tensorflow as tf
my_graph = tf.Graph()
用tf.Session(graph = my_graph)作为sess:
    x = tf.constant([1,3,6])
    y = tf.constant([1,1,1])
    op = tf.add(x,y)
    result = sess.run(fetches = op)
    print(result)
>>> [2 4 7]

预测模型

现在您已经知道TensorFlow是如何工作的,您必须学习如何创建一个预测模型。简而言之,

机器学习算法 + 数据 = 预测模型

构建模型的过程如下所示:

创建预测模型的过程

正如您所看到的,该模型由一个机器学习算法“训练”数据组成。当你有这个模型时,你会得到这样的结果:

预测工作流程

您要创建的模型的目标是按类别对文本进行分类,我们定义:

输入:文本,结果:类别

我们有一个包含所有文本的训练数据集(每个文本都有一个标签,表明它属于哪个类别)。在机器学习中,这种类型的任务被命名为监督学习

“我们知道正确的答案。该算法迭代地对训练数据进行预测,并由教师纠正。“ - Jason Brownlee

你会把数据分类到不同的类别,所以它也是一个分类任务。

为了创建模型,我们将使用神经网络。

神经网络

神经网络是一种计算模型(一种用数学语言和数学概念来描述系统的方法)。这些系统是自学和训练的,而不是明确的编程。

神经网络受到我们中枢神经系统的启发。他们连接了与我们的神经元相似的节点。

一个神经网络

感知器是第一个神经网络算法。这篇文章很好地解释了一个感知器的内部工作(“人造神经元内部”动画很棒)。

为了理解神经网络是如何工作的,我们实际上将用TensorFlow建立一个神经网络体系结构。在这个例子中,这个架构被Aymeric Damien使用。

神经网络架构

神经网络将有2个隐藏层(你必须选择网络将有多少隐藏层,是架构设计的一部分)。每个隐藏层的工作是将输入转换成输出层可以使用的东西

隐藏图层1

输入层和第一个隐藏层

你还需要定义第一个隐藏层有多少个节点。这些节点也被称为特征或神经元,在上面的图像中,它们由每个圆圈表示。

在输入层中,每个节点都对应于数据集中的一个单词(我们将在稍后看到它是如何工作的)。

如所解释这里,每个节点(神经元)被乘以权重。每个节点都有一个权重值,在训练阶段,神经网络调整这些值以产生正确的输出(等待,我们将在一分钟内了解更多)。

除了将每个输入节点乘以权重之外,网络还增加了一个偏差(神经网络中的偏差作用)。

在通过权重乘以输入并将这些值与偏差相加后,在您的体系结构中,数据也通过激活函数传递。这个激活函数定义了每个节点的最终输出。比喻:假设每个节点都是一个灯,激活功能告诉灯是否点亮。

许多类型的激活功能。您将使用整流线性单元(ReLu)。这个函数是这样定义的:

f(x) = max(0,x) 输出是x或0(零),以较大者为准

例如:如果x = -1,f(x)= 0________________________(零); 如果x = 0.7,则________________________f(x)= 0.7

隐藏的图层2

第二个隐藏层确实是第一个隐藏层所做的,但是现在第二个隐藏层的输入是第一个隐藏层的输出。

第一和第二隐藏层

输出层

我们终于到了最后一层,即输出层。您将使用单热编码来获取此图层的结果。在这个编码中,只有一位的值是1,其他的都是零值。例如,如果我们想编码三个类别(运动,空间和计算机图形):

+-------------------+-----------+
|    category       |   value   |
+-------------------|-----------+
|      sports       |    001    |
|      space        |    010    |
| computer graphics |    100    |
|-------------------|-----------|

所以输出节点的数量就是输入数据集的类数。

输出层的值也乘以权重,我们也加上偏差,但现在激活函数是不同的。

你想用一个类别来标记每个文本,而这些类别是相互排斥的(一个文本不能同时属于两个类别)。考虑到这一点,而不是使用ReLu激活功能,您将使用Softmax功能。该函数将每个单位的输出转换为0和1之间的值,并确保所有单位的总和等于1.这样,输出将告诉我们每个类别的每个文本的概率。

| 1.2 0.46 | 
| 0.9  - > [softmax]  - > 0.34 | 
| 0.4 0.20 |

现在你有神经网络的数据流图。将我们目前看到的所有内容翻译成代码,结果是:

# Network Parameters
n_hidden_1 = 10        # 第一层的功能
n_hidden_2 = 5         # 第二层的功能
n_input = total_words  # 词汇中的单词
n_classes = 3          # 分类:图形,空间和棒球
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)
#RELU激活的隐藏层
    layer_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)
#线性激活的输出层
    out_layer_multiplication = tf.matmul(layer_2_activation, weights['out'])
    out_layer_addition = out_layer_multiplication + biases['out']
return out_layer_addition

(稍后我们将讨论输出层激活函数的代码。)

神经网络如何学习

正如我们前面看到的那样,在训练网络的同时更新了权重值。现在我们将在TensorFlow环境中看到这是如何发生的。

tf.Variable

权重和偏差存储在变量(tf.Variable)中。这些变量通过调用来维护图形中的状态run()。在机器学习中,我们通常通过正态分布开始权重和偏差值。

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

当我们第一次运行网络时(也就是说,权值是正态分布定义的):

input values: x
weights: w
bias: b
output values: z
expected values: expected

要知道网络是否正在学习,您需要将输出值(z)与期望值(预期)进行比较。我们如何计算这种差异(损失)?有很多方法可以做到这一点。因为我们正在处理分类任务,所以损失的最好方法就是交叉熵误差

詹姆斯·D·麦卡弗里James D. McCaffrey)一篇关于为什么这是这种任务最好的方法的精彩解释

使用TensorFlow,您将使用tf.nn.softmax_cross_entropy_with_logits()方法(这里是softmax激活函数)计算交叉熵误差并计算平均误差(tf.reduce_mean())。

#构建模型
prediction = multilayer_perceptron(input_tensor, weights, biases)
#定义损失
entropy_loss = tf.nn.softmax_cross_entropy_with_logits(logits=prediction, labels=output_tensor)
loss = tf.reduce_mean(entropy_loss)

你想找到权重和偏差的最佳值,以最大限度地减少输出误差(我们得到的价值和正确的价值之间的差异)。要做到这一点,你将使用渐变下降法。更具体地说,你将使用随机梯度下降

梯度下降。来源:https//sebastianraschka.com/faq/docs/closed-form-vs-gd.html

还有很多算法来计算梯度下降,你将使用自适应矩估计(亚当)。要在TensorFlow中使用此算法,您需要传递learning_rate值,该值确定值的增量步骤以找到最佳权重值。

该方法是一个语法糖做两件事情:tf.train.AdamOptimizer(learning_rate).minimize(loss)

  1. compute_gradients(损失,<变量列表>)
  2. apply_gradients(<变量列表>)

该方法更新所有的tf.Variables新值,所以我们不需要传递变量列表。现在你有了训练网络的代码:

learning_rate = 0.001
#构建模型
prediction = multilayer_perceptron(input_tensor, weights, biases)
#定义损失
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)

数据操作

您将使用的数据集有许多英文文本,我们需要操纵这些数据将其传递到神经网络。要做到这一点,你会做两件事情:

  1. 为每个单词创建一个索引
  2. 为每个文本创建一个矩阵,如果文本中有一个单词,则值为1,否则为0

让我们看看代码来理解这个过程:

import numpy as np    #numpy 是一个从集合导入计算器的科学计算包
from collections import Counter
vocab = Counter()
text = "Hi from Brazil"
#获取所有单词
for word in text.split(' '):
    vocab[word]+=1
        
#将单词转换为索引
def get_word_2_index(vocab):
    word2index = {}
    for i,word in enumerate(vocab):
        word2index[word] = i
        
    return 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.]

在上面的例子中,文字是“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.]

您将与标签(文本的类别)相同,但是现在您将使用单一编码:

y = np.zeros((3),dtype=float)
if category == 0:
    y[0] = 1.        # [ 1.  0.  0.]
elif category == 1:
    y[1] = 1.        # [ 0.  1.  0.]
else:
     y[2] = 1.       # [ 0.  0.  1.]

运行图形并获得结果

现在是最好的部分:从模型中获得结果。首先让我们仔细看看输入数据集。

数据集

您将使用20个新闻组,这是一个包含20个主题的18.000个帖子的数据集。加载这个数据集,你将使用scikit学习库。我们将只使用3个类别:comp.graphicssci.spacerec.sport.baseball。scikit学习有两个子集:一个用于训练,一个用于测试。建议您不要看测试数据,因为这会在创建模型时影响您的选择。你不想创建一个模型来预测这个特定的测试数据,你想创建一个具有良好泛化的模型。

这是你将如何加载数据集:

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)

培训模型

神经网络术语中所有训练样例中的一个历元=一个正向传递(获得输出值)和一个反向传递(更新权重)。

记住这个tf.Session.run()方法吗?让我们仔细看看它:

tf.Session.run(fetches, feed_dict=None, options=None, run_metadata=None)

在本文开头的数据流图中,您使用了sum操作,但是我们也可以传递一个事件列表来运行。在这个神经网络运行中,您将通过两件事情:损失计算和优化步骤。

feed_dict参数是我们传递数据每次运行一步。为了传递这些数据,我们需要定义tf.placeholders(提供feed_dict)。

正如TensorFlow文档所述:

“占位符的存在完全是为了作为Feed的目标。它没有被初始化,也没有数据。“ -来源

所以你会这样定义你的占位符:

“如果使用占位符来提供输入,则可以通过使用tf.placeholder(...,shape = [ None,...])创建占位符来指定变量批量维度__。形状的None元素对应于可变尺寸的维度。“ -来源

在测试模型时,我们会用更大的批量来填充字典,这就是为什么您需要定义一个变量批量维度的原因。

get_batches()功能为我们提供了批量大小的文本数量。现在我们可以运行模型:

training_epochs = 10
# 启动图表
with tf.Session() as sess:
    sess.run(init) #inits the variables (normal distribution, remember?)
    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(len(newsgroups_train.data)/batch_size)
        # Loop over all batches
        for 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})

现在你已经训练了模型。为了测试它,你还需要创建图形元素。我们将测量模型的准确性,所以您需要得到预测值的索引和正确值的索引(因为我们使用的是单热编码),检查它们是否相等,并计算均值所有的测试数据集:

    # 测试模型
    index_prediction = tf.argmax(prediction, 1)
    index_correct = tf.argmax(output_tensor, 1)
    correct_prediction = tf.equal(index_prediction, index_correct)
    # 计算准确性
    accuracy = 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}))
>>> Epoch: 0001 loss= 1133.908114347
    Epoch: 0002 loss= 329.093700409
    Epoch: 0003 loss= 111.876660109
    Epoch: 0004 loss= 72.552971845
    Epoch: 0005 loss= 16.673050320
    Epoch: 0006 loss= 16.481995190
    Epoch: 0007 loss= 4.848220565
    Epoch: 0008 loss= 0.759822878
    Epoch: 0009 loss= 0.000000000
    Epoch: 0010 loss= 0.079848485
    Optimization Finished!
    Accuracy: 0.75

而就是这样!您使用神经网络创建了一个模型来将文本分类。恭喜!

您可以在这里看到带有最终代码 的笔记本。

提示:修改我们定义的值以查看更改如何影响训练时间和模型精度。

原文链接:https://medium.freecodecamp.org/big-picture-machine-learning-classifying-text-with-neural-networks-and-tensorflow-d94036ac2274

原文作者:Déborah Mesquita

发表于

我来说两句

1 条评论
登录 后参与评论

相关文章

来自专栏云时之间

深度学习与神经网络:mnist数据集实现手写数字识别

1924
来自专栏超智能体

YJango:TensorFlow高层API Custom Estimator建立CNN+RNN的演示

该文是YJango:TensorFlow中层API Datasets+TFRecord的数据导入的后续。

8247
来自专栏懒人开发

(3.7)James Stewart Calculus 5th Edition:Higher Derivatives

如果 微分函数 的导数 f' 依然是一个函数的话,那么这个导数的导数,可以写成 (f')' = f''。 叫 二阶导数。 莱布尼茨 写法为:

735
来自专栏专知

机器学习的大局:用神经网络和TensorFlow分类文本

本译文自Déborah Mesquita在https://medium.freecodecamp.org发表的Big Picture Machine Learn...

40514
来自专栏月色的自留地

从锅炉工到AI专家(10)

1955
来自专栏AI科技评论

深度丨机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(三)

AI科技评论按:本文是介绍用TensorFlow构建图像识别系统的第三部分。 在前两部分中,我们构建了一个softmax分类器来标记来自CIFAR-10数据集的...

3236
来自专栏Gaussic

使用TensorFlow训练循环神经网络语言模型

读了将近一个下午的TensorFlow Recurrent Neural Network教程,翻看其在PTB上的实现,感觉晦涩难懂,因此参考了部分代码,自己写了...

973
来自专栏人工智能LeadAI

layer定义 | 深度学习caffe框架

首先让我们回顾一下caffe的代码层次: blob,layer, net和solver.

731
来自专栏人工智能

随机森林的简单实现

随机森林(RandomForest):顾名思义,是用随机的方式建立一个森林,森林里面:由很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。在得到森林之后...

3317
来自专栏WD学习记录

机器学习 学习笔记(13)聚类

在无监督学习中,训练样本的标记信息是未知的,目标是通过对无标记训练样本的学习来揭示数据的内在性质及规律,为进一步的数据分析提供基础,此类学习任务中研究最多、应用...

803

扫码关注云+社区