开发人员常说, 如果你想开始机器学习, 你应该先学习算法是如何工作的. 但是我的经验表明并不是这样子.
我说你应该首先能够看到大局: 应用程序是如何工作的. 一旦你了解了这一点, 深入探索和研究算法的内部工作变得更加容易.
那么, 你如何发展一种直觉 https://www.quora.com/How-does-one-develop-intuitive-learning-And-what-are-the-key-differences-between-intuition-based-learning-and-learning-by-proof-And-which-one-do-you-prefer , 并对机器学习有一个全面的了解呢? 一个好的方法是创建机器学习模型.
假设你还不知道如何从头开始创建所有这些算法, 那么你就需要使用一个已经为你实现了所有这些算法的库. 那个库就是 TensorFlow.
在本文中, 我们将创建一个机器学习模型来将文本分类. 我们将介绍以下主题:
TensorFlow 如何工作
什么是机器学习模型
什么是神经网络?
神经网络如何学习
如何处理数据并将其传递给神经网络输入
如何运行模型并获得预测结果
你可能会学到很多新东西, 所以我们开始吧!
TensorFlow
TensorFlow https://www.tensorflow.org/ 是一个开源的机器学习库, 最初由 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 对象进行了评估(来自文档 https://www.tensorflow.org/api_docs/python/tf/Session ). 为此, 我们需要定义在会话中使用哪个图表:
- 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 http://machinelearningmastery.com/supervised-and-unsupervised-machine-learning-algorithms/
你会把数据分类到不同的类别, 所以它也是一个分类任务.
为了创建模型, 我们将使用神经网络.
神经网络
神经网络是一种计算模型(一种用数学语言和数学概念来描述系统的方法). 这些系统是自学和训练的, 而不是明确的编程.
神经网络受到我们中枢神经系统的启发. 他们连接了与我们的神经元相似的节点.
一个神经网络
感知器是第一个神经网络算法. 这篇文章 https://appliedgo.net/perceptron/ 很好地解释了一个感知器的内部工作("人造神经元内部" 动画很棒).
为了理解神经网络是如何工作的, 我们实际上将用 TensorFlow 建立一个神经网络体系结构. 在这个例子中, https://github.com/aymericdamien/TensorFlow-Examples/blob/master/notebooks/3_NeuralNetworks/multilayer_perceptron.ipynb 这个架构被 Aymeric Damien https://github.com/aymericdamien 使用.
神经网络架构
神经网络将有 2 个隐藏层(你必须选择 http://stats.stackexchange.com/questions/181/how-to-choose-the-number-of-hidden-layers-and-nodes-in-a-feedforward-neural-netw 网络将有多少隐藏层, 是架构设计的一部分). 每个隐藏层的工作是将输入转换成输出层可以使用的东西 http://stats.stackexchange.com/questions/63152/what-does-the-hidden-layer-in-a-neural-network-compute .
隐藏图层 1
输入层和第一个隐藏层
你还需要定义第一个隐藏层有多少个节点. 这些节点也被称为特征或神经元, 在上面的图像中, 它们由每个圆圈表示.
在输入层中, 每个节点都对应于数据集中的一个单词(我们将在稍后看到它是如何工作的).
如所解释这里 https://appliedgo.net/perceptron/ , 每个节点 (神经元) 被乘以权重. 每个节点都有一个权重值, 在训练阶段, 神经网络调整这些值以产生正确的输出(等待, 我们将在一分钟内了解更多).
除了将每个输入节点乘以权重之外, 网络还增加了一个偏差(神经网络中 http://stackoverflow.com/questions/2480650/role-of-bias-in-neural-networks 的偏差作用 http://stackoverflow.com/questions/2480650/role-of-bias-in-neural-networks ).
在通过权重乘以输入并将这些值与偏差相加后, 在您的体系结构中, 数据也通过激活函数传递. 这个激活函数定义了每个节点的最终输出. 比喻: 假设每个节点都是一个灯, 激活功能告诉灯是否点亮.
有许多类型的激活功能 https://en.wikipedia.org/wiki/Activation_function . 您将使用整流线性单元(ReLu). 这个函数是这样定义的:
f(x) = max(0,x) 输出是 x 或 0(零), 以较大者为准
例如: 如果 x = -1, 则 f(x)= 0________________________(零); 如果 x = 0.7, 则________________________f(x)= 0.7.
隐藏的图层 2
第二个隐藏层确实是第一个隐藏层所做的, 但是现在第二个隐藏层的输入是第一个隐藏层的输出.
第一和第二隐藏层
输出层
我们终于到了最后一层, 即输出层. 您将使用单热编码 https://en.wikipedia.org/wiki/One-hot 来获取此图层的结果. 在这个编码中, 只有一位的值是 1, 其他的都是零值. 例如, 如果我们想编码三个类别(运动, 空间和计算机图形):
- +-------------------+-----------+
- | category | value |
- +-------------------|-----------+
- | sports | 001 |
- | space | 010 |
- | computer graphics | 100 |
- |-------------------|-----------|
所以输出节点的数量就是输入数据集的类数.
输出层的值也乘以权重, 我们也加上偏差, 但现在激活函数是不同的.
你想用一个类别来标记每个文本, 而这些类别是相互排斥的(一个文本不能同时属于两个类别). 考虑到这一点, 而不是使用 ReLu 激活功能, 您将使用 https://en.wikipedia.org/wiki/Softmax_function 功能. 该函数将每个单位的输出转换为 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(). 在机器学习中, 我们通常通过正态分布 https://en.wikipedia.org/wiki/Normal_distribution 开始权重和偏差值.
- 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) 与期望值 (预期) 进行比较. 我们如何计算这种差异(损失)? 有很多方法可以做到这一点. 因为我们正在处理分类任务, 所以损失的最好方法就是交叉熵误差 https://en.wikipedia.org/wiki/Cross_entropy .
詹姆斯. D. 麦卡弗里 https://jamesmccaffrey.wordpress.com/ (James D. McCaffrey) https://jamesmccaffrey.wordpress.com/ 写了 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/ 一篇关于为什么这是这种任务最好的方法的精彩解释 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/ .
使用 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://en.wikipedia.org/wiki/Gradient_descent . 更具体地说, 你将使用随机梯度下降 https://en.wikipedia.org/wiki/Stochastic_gradient_descent .
- tf.train.AdamOptimizer(learning_rate).minimize(loss)
- compute_gradients(损失,<变量列表>)
- apply_gradients(<变量列表>)
- loss = tf.reduce_mean(entropy_loss)
- optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
- 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.]
- 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.]
- 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)
- 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://cloud.tencent.com/developer/article/1007172