机器学习的大局观:使用神经网络和tensorflow来对文本分类

caimouse caimouse     2022-08-27     228

关键词:

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

 

https://medium.freecodecamp.com/big-picture-machine-learning-classifying-text-with-neural-networks-and-tensorflow-d94036ac2274

 

机器学习的开发人员常常说,如果你想学习机器学习,必须先学习算法是怎么样工作的原理,但是我的经验告诉我,不是这样的。

 

我说,你应该首先能够看到大局:机器学习的应用程序是怎么样工作的。一旦你理解它,你就可以轻松地深入学习和体会到机器学习算法的工作原理。

 

所以怎么样才形成一种直觉的知识和通过大局观来理解机器学习呢?我认为一个好的方法是通过创建机器学习的模型。

 

如果你仍然不知道如何从头开始创建所有的这些算法,也没有关系,你可以使用一些现成的机器学习算法库来学习,比如使用TensorFlow

 

在这篇文章里,我们主要学习文本分类的机器学习的模型,所以有由下面的几步学习:

1. TensorFlow是怎么样工作的

2. 机器学习的模型是什么

3. 神经网络是什么

4. 神经网络是怎么样学习

5. 怎么样操作数据,并且让数据通过神经网络计算

6. 怎么样运行这个模型和获取预测结果

在这个过程里,你发现有很多不懂的知识需要学习,让我们立即开始吧!

 

TensorFlow

TensorFlow是一个GOOGLE开源的机器学习库,它的名称就提示了我们学习和理解它的工作原理了:张量是多维的数组,它流过所有节点图。

 

tf.Graph

TensorFlow里所有的计算都表示为数据流图的计算。数据流图主要有两大部分组成:

l tf.Operation集合,它表示所有计算单元。

l tf.Tensor集合,它表示数据单元。

通过查看下面这张数据流图,就明白它的工作过程:


假如你定义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()
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()来运行,这个方法执行了图计算的一步运算,在这些计算里只会运行需要计算的操作,然后把需要求解的值计算出来并取回来(fetches)。在上面这个例子里,就是对两个张量进行相加的操作:

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的工作过程了,接着下来学习怎么样创建一个预测模型,简单地说:

Machine learning algorithm + data = predictive model

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

 

因而构造这个模型如下:


从上面可以看到,模型主要由机器学习算法通过数据训练来组成的,当你把这个模型训练之后,就可以使用它如下面这样进行预测了:


由于我们定义的模型是用来对文本进行分类,所以定义如下:

 

输入 文本, 输出 分类

 

接着,我们需要一个做了标记的文本训练集(每个文本对应一个分类标志)。在机器学习里,这种情况叫做监督学习(Supervised learning)。

“We know the correct answers. The algorithm iteratively makes predictions on the training data and is corrected by the teacher.” — Jason Brownlee

 

由于是把数据分类,所以这个又是分类任务。

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

 

神经网络

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

 

神经网络的灵感来自我们的中枢神经系统,相互连接的节点就像我们的神经单元一样:

 


第一个神经网络的算法是感知机,这篇文章介绍了感知机的工作原理(https://appliedgo.net/perceptron/)。

 

为了理解神经网络是怎么样使用TensorFlow建立和工作,可以查看这个例子(https://github.com/aymericdamien/TensorFlow-Examples/blob/master/notebooks/3_NeuralNetworks/multilayer_perceptron.ipynb)。

 

神经网络架构

本神经网络由两个隐藏层组成(至于选择多少层隐藏层,这是属于神经网络的架构设计)。每个隐藏层的工作是将输入转换成输出层可以使用的东西。

 

第一层隐藏层

 

 

你需要定义第一层隐藏层有多少个节点,这些节点也叫做特征值或者神经元,在上图里表示为圆圈。

 

在输入层里每个节点表示一个数据集的单词(后面会看到怎么样表示)。

 

如图所示,每个节点(神经元)都乘以一个权重值。每个节点有一个权重值,在训练期间,神经网络通过调整这些权重值,以便可以生产一个正确的输出。

 

除了每个输入节点乘以权重值之外,神经网络还需要加上一个偏差值 http://stackoverflow.com/questions/2480650/role-of-bias-in-neural-networks)。

 

在我们的构架里输入的值乘以权重值,加上偏差值,然后通过激活函数。激活函数是定义在每个输出节点的后面,可以这样来理解:假设每个节点都是灯,激活函数告诉灯是否亮。

 

激活函数有很多种类型,最常使用的非线性激活函数(ReLu),它定义如下:

f(x) = max(0,x) [the output is x or 0 (zero), whichever is larger]

例如:如果x = -1,那么f(x) = 0;如果x = 0.7, 那么f(x) = 0.7

 

第二层隐藏层

其实第二层隐藏层的工作方式与第一层是一样的,只不过,第二层是从第一层进行输入的:

 


输出层

最后我们来到最后一层:输出层。需要使用one-hot-encodinghttps://en.wikipedia.org/wiki/One-hot)来表示输出结果,仅有一个元素为1,其它元素为0.假如,我们使用三个分类(体育、太空和计算机图形学):

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

 

由上可知,输出节点的数目就是数据集分类的数目。

 

输出层的数值也是乘以权重值,并加上偏差值,但最后的激活函数是不一样的。

 

您希望将每个文本标记为一个类别,这些类别是相互排斥的(意味着每个文本不可能同时属于两种类别)。考虑到这些,显然使用非线性激活函数ReLu就不行了,因而采用Softmax函数(https://en.wikipedia.org/wiki/Softmax_function),这个函数转换输出结果为01之间,且所有元素相加起来等于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()来维护和更新这些变量的状态。在机器学习的初始阶段,我们常常把这些权重值和偏差值初始化为正态分布的值(https://en.wikipedia.org/wiki/Normal_distribution)。

weights = {

    'hidden1': 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 = {

    'biases1': 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)之间的差异,然后通过计算它们之间的差(损失)?计算这种之间的差别有很多方式,但我们这里的任务是分类任务,因此最好的损失函数是采用交叉熵的方式(https://en.wikipedia.org/wiki/Cross_entropy)。

 

James D. McCaffrey写了一篇文章来说明为什么采用这种方式是最好的分类方法(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_entroy_with_logits() ,接着使用平均误差(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://en.wikipedia.org/wiki/Stochastic_gradient_descent):


同样也有很多算法来计算梯度下降的,在这里采用Adaptive Moment Estimation (Adam)算法计算(http://sebastianruder.com/optimizing-gradient-descent/index.html#adam)。在TensorFlow里使用这个算法时,需要输入一个学习速率的参数,这个参数决定了每一次找到最好的权重值的步伐。

 

方法tf.train.AdamOptimizer(learning_rate).minimize(loss)是分成两步计算的,如下:

1. 计算梯度(损失值, <变量列表>

2. 更新梯度(<变量列表>

这个方法更新了所有变量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 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] = 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.]

对于标签也可采用同样方法,不过是采用one-hot向量的方式:

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个新闻组(http://qwone.com/~jason/20Newsgroups/)的数据,20个主题组成,大概有18000个篇文章。要加载这些数据需要使用scikit-learn库,在这里仅使用三个分类:comp.graphics, sci.space rec.sport.baseballScikit-learn有两个集合组成:一个训练集和测试集。建议你不要看测试数据,因为在创建模型时会干扰你的选择。你不想创建一个模型来预测这个特定的测试数据,你想创建一个模型,具有良好的泛化。

 

下面就是加载数据的代码:

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)

 

在刚开始的神经网络的数据流图,我们使用相加的操作,但现在我们能传送一系列的操作了。在神经网络里,你主要做两件事情:损失值计算和每一步优化。

 

参数feed_dict是每一步运行时的传送数据的参数,为了传送数据,需要使用类(tf.placeholders)定义变量。

TensorFlow的文档里是这样描述的:

A placeholder exists solely to serve as the target of feeds. It is not initialized and contains no data.” — Source

 

所以定义如下:

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

 

训练时可以使用分批进行:

If you use placeholders for feeding input, you can specify a variable batch dimension by creating the placeholder with tf.placeholder(, shape=[None, ]). The None element of the shape corresponds to a variable-sized dimension.” — Source

 

我们将字典具有较大的批量测试时的模型,这就是为什么你需要定义一个变量的批处理尺寸。

因此定义函数get_batches()get_batches()来获取批量:

training_epochs = 10
# Launch the graph
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})

到这里已经有一个被训练的模型了,为了测试它,必须创建一个测试运行图。我们将测量模型的准确性,所以你需要得到预测值的指数和正确值的索引(因为我们使用的是一个热编码),检查它们是否相等,并计算所有测试数据集的平均值:

 

# Test model

    index_prediction = tf.argmax(prediction, 1)

    index_correct = tf.argmax(output_tensor, 1)

    correct_prediction = tf.equal(index_prediction, index_correct)

    # Calculate accuracy

    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://github.com/dmesquita/understanding_tensorflow_nn

 

有什么问题或建议吗?在评论后面写上。哦,谢谢阅读!

1. TensorFlow API攻略

http://edu.csdn.net/course/detail/4495

tensorflow简明入门教程(代码片段)

...在热了,有几个重量级的针对经验丰富的数据科学家和对神经网络感兴趣的新手平台。TensorFlow是其中之一,TensorFlow是Google一年前开源的一个机器学习库。在这篇文章中,我向你介绍TensorFlow的基础知识,并且为你讲解几个在图像... 查看详情

使用javascript实现机器学习和神经学网络

...这个话题有一些基本的了解。我会使用Encon(一个先进的神经网络和机器学习框架)这个框架,并向你们展示如何用这个框架来实现光学字符辨识,模拟退火法,遗传算法和神经网络。Encog同时包括了几个GUI窗体小部件,这些小 查看详情

人工智能python深度学习库都有哪些

...。其核心是一个数学表达式的编译器,专门为处理大规模神经网络训练的计算而设计。Theano很好地整合了Numpy,可以直接使用Numpy的Ndarray,使得API接口学习成本大为降低;其计算稳定性好,可以精准地计算输出值很小的函数;可动... 查看详情

深度学习和传统的人工神经网络机器学习有啥区别? [关闭]

】深度学习和传统的人工神经网络机器学习有啥区别?[关闭]【英文标题】:WhatisthedifferencebetweenDeepLearningandtraditionalArtificialNeuralNetworkmachinelearning?[closed]深度学习和传统的人工神经网络机器学习有什么区别?[关闭]【发布时间】... 查看详情

机器学习算法神经网络和深度学习-4重要的bp网络使用总结,了解bp神经网络的魅力

目录BP神经网络需要注意的地方。数值型字段的预处理方式类别型字段的预处理方式:目标字段的数据预处理:实际案例BP神经网络与逻辑回归、线性回归及非线性回归间的关系。BP神经网络的优缺点:我的主页:... 查看详情

图形密码的用户认证,网络通信和安全的大局在哪里?

...面临的弱点,例如肩部冲浪攻击、字典攻击等。我已经在使用mysql和htm 查看详情

深度学习和机器学习的区别是啥

...,其本身也会用到有监督和无监督的学习方法来训练深度神经网络。但由于近几年该领域发展迅猛,一些特有的学习手段相继被提出(如残差网络),因此越来越多的人将其单独看作一种学习的方法。3、机器学习最基本的做法... 查看详情

sklearn与tensorflow机器学习实用指南第二版

...七、集成学习和随机森林八、降维十、使用Keras搭建人工神经网络十一、训练深度神经网络十二、使用TensorFlow自定义模型并训练十三、使用TensorFlow加载和预处理数据十四、使用卷积神经网络实现深度计算机视觉十五、使用RNN和CN... 查看详情

机器学习和深度学习的关系啦!(?´?`?)

...从简单特征中提取复杂特征。最初的深度学习是利用深度神经网络(DNN)(超过三层的神经网络模型)来解决特征表达的一种学习过程。深度神经网络本身并不是一个全新的概念,可以大致理解为包含多个隐含层的神经网络结构... 查看详情

人工智能领域常用的开源框架和库(含机器学习/深度学习/强化学习/知识图谱/图神经网络)

【说在前面】本人博客新手一枚,象牙塔的老白,职业场的小白。以下内容仅为个人见解,欢迎批评指正,不喜勿喷![认真看图][认真看图]【补充说明】本文主要讨论人工智能领域中常用的支持Python编程语言的开源框架和库,... 查看详情

基于神经网络和遗传算法的飞鹦鹉机器学习(代码片段)

这是一个HTML5项目的源代码,该项目使用神经网络和遗传算法在FlappyBird视频游戏中实现机器学习算法。该程序教一只小鸟如何以最佳方式拍打,以便尽可能长时间地安全地飞过障碍物。所有代码都是用HTML5编写的,使... 查看详情

ai人工智能机器学习深度学习学习路径及推荐书籍

...学习基础知识:了解深度学习的基本概念和算法,如前馈神经网络、循环神经网络、卷积神经网络等。计算机视觉或自然语言处理等领域的基础知识:Pytorch可以应用于各种领域,比如计算机视觉和自然语言处理等,因此需要了... 查看详情

如何用java开始机器学习

...模的机器学习和数据挖掘的模式集合3.Neuroph–面向对象的神经网络DL4J–深度学习DL4J是一个能帮助你配置多层神经网络的工具。它为JVM提供了深度学习且伴随快速原型设计和大规模定制,同时注重比配置更多的约定。DL4J是由Java... 查看详情

14深度学习-卷积(代码片段)

...一种实现机器学习的技术和学习方法。 2. 全连接神经网络与卷积神经网络的联系与区别。解析:卷积神经网络也是通过一层一层的节点组织起来的。和全连接神经网络一样,卷积神经网络中的每一个节 查看详情

python3.9.13能不能安装torch模块

...大的编程框架,可以用来实现许多机器学习算法,如深度神经网络,卷积神经网络,递归神经网络等。要安装Torch,您需要首先安装Python3.9.13,然后使用pip命令安装Torch:pipinstalltorch安装完成后,您可以使用Python脚本来调用Torch模... 查看详情

机器学习介绍及基本概念

...机森林    4.朴素贝叶斯     5.KNN    6.神经网络回归  针对连续型输出变量进行预测,也就是所谓的回归分析  例如,假定我们想预测学生SAT考试中数学科目的成绩。如果花费在学习上的时间和最终的考试... 查看详情

学习《神经网络与机器学习(第3版)》高清英文pdf+中文pdf

神经网络是计算智能和机器学习的重要分支,在诸多领域都取得了很大的成功。在众多神经网络著作中,影响最为广泛的是SimonHaykin的《神经网络原理》(第3版更名为《神经网络与机器学习》)。结合近年来神经网络和机器学习... 查看详情

机器学习入门之四:机器学习的方法-神经网络(转载)

  转自 飞鸟各投林  神经网络    神经网络(也称之为人工神经网络,ANN)算法是80年代机器学习界非常流行的算法,不过在90年代中途衰落。现在,携着“深度学习”之势,神经网络重装归来,重新成为最强大... 查看详情