开源中国

我们不支持 IE 10 及以下版本浏览器

It appears you’re using an unsupported browser

为了获得更好的浏览体验,我们强烈建议您使用较新版本的 Chrome、 Firefox、 Safari 等,或者升级到最新版本的IE浏览器。 如果您使用的是 IE 11 或以上版本,请关闭“兼容性视图”。
图解机器学习:神经网络和 TensorFlow 的文本分类 - 技术翻译 - 开源中国社区

图解机器学习:神经网络和 TensorFlow 的文本分类 【已翻译100%】

oschina 推荐于 1个月前 (共 13 段, 翻译完成于 04-19) 评论 10
收藏  
159
推荐标签: TensorFlow 待读

开发人员经常说,如果你想开始机器学习,你应该首先学习算法。但是我的经验则不是。

我说你应该首先了解:应用程序如何工作。一旦了解了这一点,深入探索算法的内部工作就会变得更加容易。

那么,你如何 开发直觉学习,并实现理解机器学习这个目的?一个很好的方法是创建机器学习模型

假设您仍然不知道如何从头开始创建所有这些算法,您可以使用一个已经为您实现所有这些算法的库。那个库是 TensorFlow

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

  1. TensorFlow 的工作原理

  2. 什么是机器学习模型

  3. 什么是神经网络

  4. 神经网络如何学习

  5. 如何操作数据并将其传递给神经网络

  6. 如何运行模型并获得预测结果

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

总长
 翻译得不错哦!

TensorFlow

TensorFlow 是一个机器学习的开源库,由 Google 首创。库的名称帮助我们理解我们怎样使用它:tensors 是通过图的节点流转的多维数组。

tf.Graph

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

  • 一类 tf.Operation,表示计算单元

  • 一类 tf.Tensor,表示数据单元

要查看这些是怎么工作的,你需要创建这个数据流图:


(计算x+y的图)

你需要定义 x = [1,3,6] 和 y = [1,1,1]。由于图用 tf.Tensor 表示数据单元,你需要创建常量 Tensors:

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 对象是被计算过的(从文档中)。为了做到这些,我们需要在 Session 中定义哪个图将被使用到:

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

为了执行操作,你需要使用方法 tf.Session.run()。这个方法通过运行必要的图段去执行每个 Operation 对象并通过参数 fetches 计算每一个 Tensor 的值的方式执行 TensorFlow 计算的一'步':

import tensorflow as tf
my_graph = tf.Graph()
with tf.Session(graph=my_graph) as 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 的工作原理,那么你得知道怎样创建预测模型。简而言之

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

构建模型的过程就是这样:

(构建预测模型的过程)

正如你能看到的,模型由数据“训练过的”机器学习算法组成。当你有了模型,你就会得到这样的结果:

(预测工作流)

你创建的模型的目的是对文本分类,我们定义了:

input: text, result: category

我们有一个使用已经标记过的文本(每个文本都有了它属于哪个分类的标记)训练的数据集。在机器学习中,这种任务的类型是被称为监督学习

 “我们知道正确的答案。该算法迭代的预测训练数据,并由老师纠正
” —  Jason Brownlee

你会把数据分成类,因此它也是一个分类任务。

为了创建这个模型,我们将会用到神经网络。

我是菜鸟我骄傲
 翻译得不错哦!

神经网络

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

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

(一个神经网络)

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

为了理解神经网络的工作原理,我们将会使用 TensorFlow 建立一个神经网络架构。在这个例子中,这个架构被 Aymeric Damien 使用过。

我是菜鸟我骄傲
 翻译得不错哦!

神经网络架构

神经网络有两个隐藏层(你得选择 网络会有多少隐藏层,这是结构设计的一部分)。每一个隐藏层的任务是 把输入的东西转换成输出层可以使用的东西

隐藏层 1

(输入层和第一个隐藏层)

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

输入层的每个节点都对应着数据集中的一个词(之后我们会看到这是怎么运行的)

如 这里 所述,每个节点(神经元)乘以一个权重。每个节点都有一个权重值,在训练阶段,神经网络会调整这些值以产生正确的输出(过会,我们将会学习更多关于这个的信息)

除了乘以没有输入的权重,网络也会增加一个误差 (在神经网络中误差的角色)。

在你的架构中,将输入乘以权重并将值与偏差相加,这些数据也要通过激活函数传递。这个激活函数定义了每个节点的最终输出。比如说:想象一下,每一个节点是一盏灯,激活函数决定灯是否会亮。

有很多类型的激活函数。你将会使用 Rectified Linear Unit (ReLu)。这个函数是这样定义的:

f(x) = max(0,x)  [输出 x 或者 0(零)中最大的数]

例如:如果 x = -1,  f(x) = 0(zero); 如果 x = 0.7, f(x) = 0.7.

我是菜鸟我骄傲
 翻译得不错哦!

隐藏层 2

第二个隐藏层做的完全是第一个隐藏层做的事情,但现在第二层的输入是第一层的输出。

(第一和第二隐藏层)

输出层

现在终于到了最后一层,输出层。你将会使用 One-Hot 编码 得到这个层的结果。在这个编码中,只有一个比特的值是 1,其他比特的值都是 0。例如,如果我们想对三个分类编码(sports, space 和computer graphics)编码:

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

因此输出节点的编号是输入的数据集的分类的编号。

输出层的值也要乘以权重,并我们也要加上误差,但是现在激活函数不一样。

你想用分类对每一个文本进行标记,并且这些分类相互独立(一个文本不能同时属于两个分类)。考虑到这点,你将使用 Softmax 函数而不是 ReLu 激活函数。这个函数把每一个完整的输出转换成 0 和 1 之间的值,并且确保所有单元的和等于一。这样,输出将告诉我们每个分类中每个文本的概率。

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

现在有了神经网络的数据流图。把我们所看到的都转换为代码,结果是:

# 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 activation
    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)
# Output layer with linear activation
    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)和期望值(expected)。我们要怎么计算这个的不同(损耗)呢?有很多方法去解决这个问题。因为我们正在进行分类任务,测量损耗的最好的方式是 交叉熵误差

James D. McCaffrey 写了一个精彩的解释,说明为什么这是这种类型任务的最佳方法。

通过 TensorFlow 你将使用 tf.nn.softmax_cross_entropy_with_logits() 方法计算交叉熵误差(这个是 softmax 激活函数)并计算平均误差 (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)

我是菜鸟我骄傲
 翻译得不错哦!

你希望通过权重和误差的最佳值,以便最小化输出误差(实际得到的值和正确的值之间的区别)。要做到这一点,将需使用 梯度下降法。更具体些是,需要使用 随机梯度下降

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

为了计算梯度下降,将要使用 Adaptive Moment Estimation (Adam)。要在 TensorFlow 中使用此算法,需要传递 learning_rate 值,该值可确定值的增量步长以找到最佳权重值。

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

  1. compute_gradients(loss, <list of variables>)

  2. apply_gradients(<list of variables>)

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

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)

我是菜鸟我骄傲
 翻译得不错哦!

数据操作

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

  1. 为每一个工作创建索引

  2. 为每一个文本创建矩阵,在矩阵里,如果单词在文本中则值为 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 wordsfor 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] = 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 valuesfor word in text.split():
    matrix[word2index[word]] += 1print(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()]] += 1print(matrix)
>>> [ 1.  0.  0.]

将会与标签(文本的分类)相同,但是现在得使用独热编码(one-hot encoding):

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.]

我是菜鸟我骄傲
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(10)
Ctrl/CMD+Enter

收藏了,准备学习一下机器学习

引用来自“为为02”的评论

收藏了,准备学习一下机器学习
是的,就是看后比看前更不懂,呵呵。
图例是个很牛逼的玩意,尤其是很好的思维导读!!!
棒!
mark

引用来自“为为02”的评论

收藏了,准备学习一下机器学习

引用来自“久永”的评论

是的,就是看后比看前更不懂,呵呵。
哈哈,我也是一脸的蒙比
一脸懵逼的点进来。
马克
介绍感知机的那篇不错
基础知识薄弱 很多东西不好去理解. 看了遍 感知上知道大概怎么回事而已了.....
顶部