从现在开始,我们才真正进行人工神经网络的学习,我们后面简称神经网络。

第2章 人工神经收集2_神经收集_函数 计算机

简而言之,神经网络便是神经元的凑集,而前面我们提到的感知机便是被提出的第一个神经网络。
但是,它办理不了异或(XOR Problem)问题。

我们大略复习一下什么是异或问题?异或问题实际上便是逻辑运算,看看下表:

逻辑变量

逻辑变量

异或

A

B

AB

A+B

AB+BA

0

0

0

0

0

1

1

1

1

0

0

0

0

1

1

1

1

0

1

1

三角形代表1,圆圈代表0。
逻辑与和逻辑或是分布在两侧的,可以用一条直线分开,但是异或则无法用直线分开。

我们可以从上图中看到逻辑与和逻辑或都是分布在两侧的,可以用一条直线分开,但是异或则无法用直线分开。
以是,感知机办理的是线性可分问题,不能办理线性不可分问题。

线性可分(左)和线性不可分(右)。

这时候,加拿大著名学者辛顿(Geoffrey Hinton)登场了,首先办理了感知机的异或问题,在1974年把1969年被Minsky杀去世的Perceptron成功复活。

Geoffrey Hinton的思想非常大略,‌即“多则不同”,‌意味着单个神经元无法办理的问题可以通过多个神经元构成的网络来共同完成。
‌也便是说,单层感知机办理不了异或问题,就多加一层,即多层感知机(MLP,Multilayer Perceptron)就可以办理了。

多层感知机与深度神经网络。

我们学习到的多层感知机,包括后面重点学习的卷积神经网络等都属于阶层型神经网络。
即按照层(Layer)划分神经单元(units),通过连接这些神经单元处理旗子暗记。
每个单元也可以被称为神经节点或神经元(根据生物学来源定义)。
全体神经网络的构造包括:输入层(hidden layer)、隐蔽层(也被称为中间层)和输出层。
各层分别实行特定的旗子暗记处理操作。

输入层

输入层是卖力读取神经网络的吸收信息,这个层的神经单元没有输入箭头。

详细地说,输入层是演习集的实例特色向量传入,经由连接点的权重传入下一层,这一层的输出是下一层的输入。
输入层神经元的数量即是向量的维度,即向量中元素的个数。

隐蔽层

隐蔽层是位于输入层和输出层之间的一层或多层神经元的凑集,即除了输入层和输出层以外的其它各层的总称。
隐蔽层不直接接管外界旗子暗记,也不直接向外界发送旗子暗记,在神经网络中的浸染是中间的黑盒子,卖力对输入数据进行特色提取和转换,从而实现繁芜的非线性映射关系。

在神经网络中,隐蔽层是实际处理信息的部分。

隐蔽层的层数及每一层神经元个数可以是任意的。

最著名的深度学习(Machine Learning, ML)便是指含有的隐蔽层数量大于或即是2的神经网络。

思考:深度学习中的“深度”是指的什么意思?

隐蔽层的数量大于即是2,即超过3层的神经网络。

输出层

输出层是神经网络的末了一层,其输出是神经网络对付输入数据的预测或分类结果。
输出层的神经网络数根据详细的任务进行调度,以适应不同的运用处景。

输入层和输出层都只有一层。
每一层中的加权求和,然后根据非线性方程转化为输出。
如果有足够多的隐蔽层和足够大的演习集,可以拟合出任何函数。

下面我们用Visio绘制一个大略的多层感知机图,理解一下神经网络框架图绘制工具。

神经网络框架示意图。

也可以写一个Python程序,用Matplotlib自动绘图,不过还是Visio、AI之类的手动绘图工具画的更好看些:

神经网络框架示意图(编程自动绘出)。

代码示例:

import matplotlib.pyplot as plt import numpy as np # 定义神经网络层的大小 input_nodes = 3 hidden_nodes = 4 output_nodes = 2 # 打算层的位置 y_positions = [-1, 0, 1] # 假设有三层:输入层、隐蔽层、输出层 # 创建一个画布 fig, ax = plt.subplots(figsize=(8, 4)) # 绘制节点 # 输入层 input_x = np.linspace(-input_nodes / 2, input_nodes / 2, input_nodes) ax.scatter(input_x, np.full_like(input_x, y_positions[0]), s=100, color='blue', label='Input Layer') # 隐蔽层 hidden_x = np.linspace(-hidden_nodes / 2, hidden_nodes / 2, hidden_nodes) ax.scatter(hidden_x, np.full_like(hidden_x, y_positions[1]), s=100, color='red', label='Hidden Layer') # 输出层 output_x = np.linspace(-output_nodes / 2, output_nodes / 2, output_nodes) ax.scatter(output_x, np.full_like(output_x, y_positions[2]), s=100, color='green', label='Output Layer') # 绘制所有连接 # 输入层到隐蔽层 for input_idx in range(input_nodes): for hidden_idx in range(hidden_nodes): ax.plot([input_x[input_idx], hidden_x[hidden_idx]], [y_positions[0], y_positions[1]], 'k-', linewidth=1, alpha=0.5) # 隐蔽层到输出层 for hidden_idx in range(hidden_nodes): for output_idx in range(output_nodes): ax.plot([hidden_x[hidden_idx], output_x[output_idx]], [y_positions[1], y_positions[2]], 'k-', linewidth=1, alpha=0.5) # 添加图例 ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize='small') # 设置坐标轴范围 ax.set_xlim(-2, 2.5) # 轻微扩大x轴范围以避免连接线被裁剪 ax.set_ylim(-1.5, 1.5) # 隐蔽坐标轴 ax.axis('off') # 显示图形 plt.show()

从神经网络的构造示意图我们可以看出:

人工神经网络(Artificial Neural Network,ANN)简称神经网络 (NN),是基于生物学中神经网络的基本事理,在理解和抽象了人脑构造和外界刺激相应机制后,以网络拓扑知识为理论根本,仿照人脑的神经系统对繁芜信息的处理机制的一种数学模型。
大略地说,神经网络便是多个神经元组合到一起的凑集。

问题:假设有一台机器,接管了一个问题,比如如何进行手写数字识别,即对手写数字进行分类问题,机器做了一些“思考”,并输出了一个答案。
就犹如我们用眼睛看到了手写数字的图片,通过大脑剖析,得出是什么数字的结论。

这个机器模型可以利用神经网络。
我们来看看实际中的运用:

数字“8”的手写数字图像,我们进行了压缩,由1818=324个像素构成。

下图是我利用PowerPoint绘制的一个示意图,PowerPoint是不是也是一个不错的选择?看大家的利用习气:

上图中我们利用的网络一共由4层神经元组成的,但本色上只有3层神经元有权重,因此将其称为“3层网络”。
输入层到输出层依次称为第0层工具1018=324个神经元(根据输入数据的实际情形决定)、第1层利用15个神经元、第2层利用10个神经元(隐蔽层的神经元设计根据实际情形进行优化后决定)、第3层(10个神经元,10分类)(层号之以是从0开始,是为了方便后面基于Python进行实现)。

这个大略神经网络的特色是,前一层的神经元与下一层的所有神经元都有箭头连接,这样的层布局称为全连接层(full connected layer)。
这种形状,对付打算机的打算而言是十分有效的。

问题:神经网络中旗子暗记是如何通报的呢?

2.2.2 激活函数

神经元是神经网络的基本构造,前面已经先容,它的设计灵感完备来源于生物学上神经元的信息传播机制。
生物神经元有2种状态:愉快和抑制。
一样平常情形下 ,大多数的神经元是出于抑制状态,但一旦某个神经元收到刺激,电位超过阈值,神经元就会被激活,出于愉快状态,进而可以进行信息通报。

激活函数(Activation Function)是在人工神经网络的神经元上运行的函数,卖力将神经元的输入映射到输出端,激活函数将神经网络中将输入旗子暗记的总和转换为输出旗子暗记。
激活函数大多是非线性函数,才能将多层感知机的输出转换为非线性,使得神经网络可以任意逼近任何非线性函数,进而可以运用到浩瀚的非线性模型中。

早期的激活函数是阶梯函数:

左图是阶梯函数的图像,映射的关系是:

阶梯函数是当时输出为1,否则输出为0,这是最大略的一种通报函数用法,是最神经元神经冲动的一种大略仿照。

现在常用的激活函数紧张包括:

sigmoid函数

在逻辑回归中我们学习过sigmoid函数,也叫Logistic函数,该函数是将取值为 (−∞,+∞) 的数映射到 (0,1) 之间,当以概率形式表示预测值时,一样平常利用这个函数。

sigmoid函数的公式以及图形如下:

sigmoid函数作为最早广泛利用的非线性激活函数,但现在已经不常用了,紧张是它具有以下二个缺陷:

1)当 z 值非常大或者非常小时,通过上图我们可以看到,sigmoid函数的导数 g′(z) 将靠近 0 。
这会导致权重 W 的梯度将靠近 0 ,使得梯度更新十分缓慢,即梯度消逝。
——关于梯度问题,我们后后面要重点谈论,也是神经网络学习中最主要的问题之一。

2)函数的输出不因此0为均值,将不便于下层的打算。
现在 sigmoid函数可用在网络末了一层,作为输出层进行二分类,只管即便不要利用在隐蔽层。

让我们从头开始构建一下sigmoid函数,在PyTorch中是已经构建好了的,直接调用就行。

import numpy as npdef sigmoid(x): s=1/(1+np.exp(-x)) return stanh函数

tanh函数,即双曲正切函数,也是早期常常利用的激活函数,比sigmoid函数更受欢迎,能为多层神经网络供应更好的性能。
该函数是将取值为 (−∞,+∞)的数映射到 (−1,1) 之间,其公式与图形为:

tanh函数的输出更多地以0为中央,在 0 附近很短一段区域内可看做线性的。
由于tanh函数均值为 0 ,因此填补了sigmoid函数均值为 0.5 的缺陷,有助于加速收敛,尤其是在演习初期,从而减少迭代次数。

tanh函数的缺陷同sigmoid函数的第一个缺陷一样,当 z 很大或很小时,g′(z) 靠近于 0 ,会导致梯度很小,权重更新非常缓慢,即梯度消逝问题。

import numpy as npdef tanh(z): s1=np.exp(z)-np.exp(-z) s2=np.exp(z)+np.exp(-z) s=s1/s2 return sReLU函数

ReLU函数又称为改动线性单元(Rectified Linear Unit),是一种分段线性函数,其填补了sigmoid函数以及tanh函数的梯度消逝问题。

ReLU函数的公式以及图形如下:

将 ReLU 函数引着迷经网络时,也引入了很大的稀疏性。
然而,由于稀疏性,韶光和空间繁芜度更低,不涉及本钱更高的指数运算,许可网络快速收敛。

import numpy as npdef rulu(z): s=np.where(x<0,0,x) return s

ReLU引入了神经元去世亡问题,当输入靠近零或为负时,函数的梯度变为零,网络将无法实行反向传播,也无法学习,也便是说,网络的大部分分量都永久不会更新,其余,它不能避免梯度爆炸问题。

softmax函数

softmax函数比较适宜作为多分类模型的激活函数,下一章会先容softmax一样平常与交叉熵丢失函数相匹配。

常日,Softmax函数只运用于输出层,把一堆实数的值映射到0-1区间,并且使他们的和为1,可以理解为对应每个种别对应的预测概率。

Softmax函数用于将输入进行归一化到(0,1),并且其和为1,普遍运用于分类模型(互斥)的预测概率值。
事实上,但凡涉及到概率的地方基本都会用到softmax,范例的就比如attention layer当中,都会利用softmax来打算attention值。

def softmax(z): z_exp = np.exp(z) z_sum = np.sum(z_exp, axis=1, keepdims=True) s = z_exp / z_sum return s

激活函数的选择也是为终极的任务目标做事的。
不存在普遍适用各种神经网络的万能的激活函数,在选择激活函数的时候,要考虑不同的条件限定,例如,如果函数可导,求导数的打算难度如何?函数光滑程度如何?输出是否保持标准化?网络的收敛速率如何?等等。

一样平常地,在用于分类器时,Sigmoid函数及其组合常日效果更好。
为了避免梯度消逝问题,又须要避免利用Sigmoid和Tanh。
如果是回归模型,在输出层上可以利用线性激活函数。
如果是浅层神经网络,如不超过4层的,可选择利用多种勉励函数,没有太大的影响。

ReLU函数是运用比较广泛的激活函数,可以作为默认选项。
深度学习每每须要大量韶光来处理大量数据,模型的收敛速率是尤为主要的以是要只管即便选择输出具有zero-centered特点的激活函数以加快模型的收敛速率。

更主要的是,激活函数仍在发展,须要跟踪业界的最新进展,并勇于探索和创新。

2.2.3 旗子暗记处理与通报

神经网络是受生物大脑启示而设计出来的系统,可以用来处理和通报旗子暗记。

生物神经元处理与通报的基本构造:

树突:接管来自其它神经元的电旗子暗记;细胞体:处理信息;轴突:将电旗子暗记通报到其它神经元。

比如,人有悲欢畅乐,那这些悲欢畅乐是受什么掌握的呢?

显然是旗子暗记。
当我们看到一些赏心悦目的景物,神经元通报出愉快的旗子暗记,我们便做出愉快的表情;当我们很悲哀时,神经元通报出悲哀的旗子暗记,我们便做出悲哀的表情。

但我们大多时候都不可能既表现悲哀又表现愉快,因此神经元须要对这些旗子暗记进行处理,得到终极的输出感情旗子暗记。
这种处理办法便是加权求和。
例如,假设感情是一个二维的向量,愉快的向量表示为:

不愉快的向量表示为:

假设这个神经元增强愉快旗子暗记(权值为2),抑制不愉快旗子暗记(权值为0),那么终极的旗子暗记可以表示为:

,即终极输出的的旗子暗记是一个愉快的旗子暗记。

神经网络也正是这样设计的,可以接管多个输入旗子暗记,为了学习神经网络旗子暗记处理与通报事情事理,须要先理解两个基本观点打算图和矢量化。

打算图

前面我们先容过,人工神经元是人工神经网络的基本单位,是有向加权弧连接起来的有向图。
这个有向图实际上便是一种打算图。

打算图(computational graph)是用图论措辞表示数学函数的一种办法,打算图用节点表示变量,用有向边(directed edge)(箭头)表示打算。
有向边的目的节点称为子节点,源节点称为父节点,打算图定义如何用父节点打算子节点:

上图的打算图分别描述了:;

一个父节点可以有2个以上的子节点,一个子节点也可以有2个以上的父节点,但是这种情形可以通过添加中间节点而转化成每个子节点只有两个父节点的情形:

上图的打算图表示一个逻辑回归模型:

打算图的节点可以是标量,也可以是向量、矩阵和张量。

PyTorch是动态图机制,在演习模型时,每迭代一次就会构建一个新的打算图。

举例:

在打算

过程中会建立如下打算图:

在上面的打算图中,节点便是参与运算的变量,在Pytorch中是用Variable()变量来封装的,而图中的边便是变量之间的运算关系。

神经网络中的神经元用节点表示,而旗子暗记通报用有向边表示。

向量化

神经网络的传播涉及到的网络层数多,每层的节点数量多,在进行打算的时候对付人类来说是一个非常艰巨的事情,如何简化打算呢?

前面我们先容了矩阵乘法,终于派上用场了,那便是神经网络内积。
矩阵许可我们压缩打算,把它们变成大略的缩写形式;许多打算机编程措辞能够理解如何与矩阵一起事情,对付这些重复性事情能够进行高效高速打算。

上图是一个大略的神经网络,省略了偏置和激活函数,只有权重。
实现神经网络旗子暗记通报时,要把稳X、W和Y的形状,特殊是X和W的对应维度的元素个数是否同等,这一点特殊主要。

import numpy as npX = np.array([1,2])print(X.shape)W = np.array([[1,3,5],[2,4,6]])print(W)print(W.shape)Y = np.dot(X,W)print(Y)

利用Numpy工具包的np.dot(多维数组的点积),可以一次性打算出Y的结果。
也便是说,无论Y的元素个数是100或是1000,都可以通过一次运算打算出结果(比单独利用for语句打算要大略得多)。
因此,通过矩阵的乘积一次性完成打算的技巧,在神经网络实现的层面上非常主要。
现在通过PyTorch能够很迅速的搭建各种神经网络构架,但是在文中最开始我们说过“What I cannot create, I do not understand.”以是,最根本的前馈神经网络,还是利用NumPy从最根本开始。

旗子暗记处理与通报实例

现在我们实现一个大略的3层神经网络,看看神经网络是如何实现旗子暗记处理与通报的。

图例:3层神经网络:输入层(第0层)有两个神经元,第1个隐蔽层(第1层)有3个神经元,第2个隐蔽层(第2层)有2个神经元,输出层(第3层)有2个神经元。

我们可以用上图的一些符号代表各层权重,不过一样平常用得也不多,这里只是方便先容矩阵打算。

首先,我们看一下从输入层的第1个神经元的旗子暗记通报:

上图中增加了表示偏置的神经元“1”。

请把稳,偏置的右下角的索引号只有一个。
这是由于前一层的偏置神经元(神经元“1”)只有一个 。
通过加权旗子暗记和偏置,我们可以进行如下打算:

也可以通过利用矩阵的乘法运算,将第一层的加权和表示如下:

个中:

利用Numpy数组实现一下:

X = np.array([1.0,0.5])W1 = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])B1 = np.array([0.1,0.2,0.3])A1 = np.dot(X,W1) + B1print(A1)

是不是特殊大略?和前面讲的矩阵打算是一样的。

神经元除了求和操作外,还有一个什么操作?——线性变换

第1层中激活函数的打算过程:Z1 = sigmoid(A1)

def sigmoid(Z): Z = 1/(1+np.exp(Z)) return ZZ1 = sigmoid(A1)print(Z1)

也很大略吧?

其它各层旗子暗记通报也一样。

值得把稳的是,末了一层的激活函数和前面的隐蔽层不一样。

在进行分类问题研究中,前面已经先容,常日利用softmax函数作为激活函数:

exp(x)表示的指数函数。
上式表示假设输出层共有n个神经元,打算第k个神经元的输出。
softmax函数的分子是输入旗子暗记的指数函数,分母是所有输入旗子暗记的指数函数的和。

特殊须要把稳的是:

softmax在打算机打算的时候有一个溢出的毛病。
softmax函数的实现要进行指数函数的运算,值会很随意马虎变得非常大。
如的值会超过20000,会变成后面有40多个0的超大值,运算结果会返回一个表示无穷大的inf。
如果进行除法打算,结果就会涌现“不愿定”的情形。

改进的办法是:

在分子和分母都乘上一个任意的常数C(值不会变),然后把C移动到指数函数(exp())中,记为logC,然后把logC更换为另一个符号C'。
C'可以是任意值,但是为了防止溢出,一样平常会利用输入旗子暗记中的最大值。

可以试一下。

a = np.array([1010,1000,990])np.exp(a)/np.sum(np.exp(a)) #softmax函数运算,不能精确运算c = np.max(a)np.exp(a-c)/np.sum(np.exp(a-c)) # 可以精确运算了

softmax函数特色:

softmax函数的输出是0.0到1.0之间的实数,并且 softmax函数的输出值的总和是1。

输出总和为1是softmax函数的一个主要性子。
正由于有了这个性子,我们才可以把softmax函数的输出阐明为“概率”。
也便是说,通过利用softmax函数,我们可以用概率的(统计的)方法处理问题。

从头开始实现一个神经网络至少是一次极宝贵的磨炼,可以帮助我们得到神经网络是如何事情的理解,这也是我们后面设计模型必不可少的。
让我们从头开始来设计一个神网络:

神经网络事实上便是多个神经元组合到一起的凑集。
我们先画一个神经网络图,包括:

输入层X

任意数量的隐蔽层

输出层?

每一层W和B之间的权重和偏置

import numpy as npdef sigmoid(x): #sigmoid函数实现 return 1/(1+np.exp(-x))def identity_function(x): #恒等函数,原样输出 return x def init_network(): # 初始化网络 network = {} network['W1'] = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]]) network['b1'] = np.array([0.1,0.2,0.3]) network['W2'] = np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]]) network['b2'] = np.array([0.1,0.2]) network['W3'] = np.array([[0.1,0.3],[0.2,0.4]]) network['b3'] = np.array([0.1,0.2]) return networkdef forward(network,x): # 前向传播 W1,W2,W3 = network['W1'],network['W2'],network['W3'] b1,b2,b3 = network['b1'],network['b2'],network['b3'] a1 = np.dot(x,W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1,W2) + b2 z2 = sigmoid(a2) a3 = np.dot(z2,W3) + b3 y = identity_function(a3) return ynetwork = init_network()x = np.array([1.0,0.5])y = forward(network,x)print(y) # [0.31682708 0.69627909]

这就构建好了一个神经网络,是不是很有造诣感?

反向传播

反向传播(backward propagation或backpropagation)指的是打算神经网络参数梯度的方法。
关于如何打算梯度等详细内容,我们不才一章神经网络的学习再学习。

2.3 分类问题数据集

分类问题是机器学习,也是我们日常生活中最常碰着的一类问题,比如去医院年夜夫诊断病人身体里的肿瘤是否是恶性的,是否是糖尿病,垃圾邮件的分类,看到的是狗还是猫是别的物体......这些问题都属于分类问题的范畴。

要通过机器学习实现 分类,首先须要构建数据集。
我们学习理解一下MNIST数据集。

MNIST 数据集( http://yann.lecun.com/exdb/mnist/ )是机器学习界的“Hello World”,是图像分类中广泛利用的数据集之一,但作为基准数据集过于大略。
本数据集来自美国国家标准与技能研究所, National Institute of Standards and Technology (NIST); 演习集 (training set) 由来自 250 个不同人手写的数字构成, 个中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的事情职员; 测试集(test set) 也是同样比例的手写数字数据。

MNIST数据集共有7万张图片,个中6万张用于演习神经网络,1万张用于测试神经网络。

每张图片是一个2828像素点的0~9的手写数字图片。
黑底白字。
黑底用0表示,白字用0~1之间的浮点数表示,越靠近1,颜色越百。

这些图片并不是传统意义上的png或者jpg格式的图片,由于png或者jpg的图片格式,会带有很多滋扰信息(如:数据块,图片头,图片尾,长度等等),这些图片会被处理成很大略单纯的二维数组——也是说完成了向量化处理。

我们把这个数组展开成一个向量,长度是 28x28 = 784。
如何展开这个数组(数字间的顺序)不主要,只要保持各个图片采取相同的办法展开。
从这个角度来看,MNIST数据集的图片便是在784维向量空间里面的点, 并且拥有比较繁芜的构造 (提醒: 此类数据的可视化是打算密集型的)。

每一个MNIST数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。
我们把这些图片设为“xs”,把这些标签设为“ys”。
演习数据集和测试数据集都包含xs和ys,比如演习数据集的图片是 mnist.train.images ,演习数据集的标签是 mnist.train.labels。

在MNIST演习数据集中,mnist.train.images 是一个形状为 [60000, 784] 的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点。
在此张量里的每一个元素,都表示某张图片里的某个像素的强度值,值介于0和1之间。

相对应的MNIST数据集的标签是介于0到9的数字,用来描述给定图片里表示的数字。
标签数据是“one-hot vectors”。
一个one-hot向量除了某一位的数字是1以外别的各维度数字都是0。
以是,数字n将表示成一个只有在第n维度(从0开始)数字为1的10维向量。
比如,标签0将表示成([1,0,0,0,0,0,0,0,0,0,0])。
因此, mnist.train.labels 是一个 [60000, 10] 的数字矩阵。

2.3.2 Fashion-MNIST数据集

由于MNIST数据集作为基准数据集过于大略,现在一样平常利用Fashion-MNIST数据集。

Fashion-MNIST 的目的是要成为 MNIST 数据集的一个直接替代品。
作为算法作者,你不须要修正任何的代码,就可以直策应用这个数据集。
Fashion-MNIST 的图片大小,演习、测试样本数及种别数与经典 MNIST 完备相同。

Fashion-MNIST克隆了MNIST的所有外在特色:

•60000张演习图像和对应Label;

•10000张测试图像和对应Label;

•10个种别;

•每张图像28x28的分辨率;

•4个GZ文件名称都一样;

……

还有Cifar、ImageNet等有名的数据集,后面再先容。

这些基准数据集,数据预处理基本上都以完成,可以直接***利用。
生命组学数据或康健医疗数据等须要我们前期经由预处理,转换成图像、自然措辞或图等数据格式。

数据的导入和处理:

数据读取:两种办法

1)***并利用PyTorch供应的内置数据集。
——这种比较大略,学习算法的时候很好用。

2) 从网站***以csv格式存储的数据,读入并转成预期的格式。
——可以自行构建自己Dataset,由于我们各种生命组学数据须要自己构建数据集,建议采取这种办法。

编程实现一下:

# 导入各种包import numpy as npimport pandas as pdimport torchfrom torch.utils.data import Dataset,DataLoaderimport torchvisionfrom torchvision import transforms# 数据的读入与加载# 首先设置数据变换image_size = 28data_transform = transforms.Compose([ # 这一步取决于后面的数据读取办法,如果利用内置数据集则不须要 # transforms.TopTLImage(), transforms.Resize(image_size), transforms.ToTensor()])# 办法一:利用torchvision自带数据集from torchvision import datasetstrain_data = datasets.FashionMNIST(root="../data", train=True, download=True, transform=data_transform)test_data = datasets.FashionMNIST(root="../data", train=False, download=True, transform=data_transform)

关于生物信息干系数据集,我们在后面的学习过程中再详细完成程干系数据处理。

2.4基于PyTorch的编程实现

PyTorch有很多种搭建神经网络的方法,最常用的是利用PyTorch中的nn模块,封装好了神经网络层,具有自动求导功能(这个我们下一章神经网络的学习中再先容)。

神经网络工具箱

torch.nn是专门为深度学习设计的工具箱,它的核心数据构造是Module类,它是一个抽象的观点,既可以表示神经网络的一层,又可以表示一个包含多层的神经网络。

我们在搭建网络模型的时候,最常见的作法是继续nn.Module,调用时先实例化,然后用__init__()中初始化,然后再forward()中进行操作。

nn.functional是PyTorch中的一个主要模块,它包含了许多构建神经网络的函数。
这些函数不具有可学习的参数,用于实行各种非线性操作、激活函数和丢失函数等。

让我们实现一下上面那个先容的那个3层神经网络:

import torch import torch.nn as nn import torch.nn.functional as F class MyNet(nn.Module): #自定义层继续nn.Module def __init__(self, input_size, hidden_size1, hidden_size2, output_size): super(MyNet, self).__init__() # 第0层:从输入层到第一个隐蔽层,以此类推 self.fc0 = nn.Linear(input_size, hidden_size1) self.fc1 = nn.Linear(hidden_size1, hidden_size2) self.fc2 = nn.Linear(hidden_size2, hidden_size2) self.fc3 = nn.Linear(hidden_size2, output_size) def forward(self, x): # 数据通过第0层,并运用ReLU激活函数,以此类推 x = F.relu(self.fc0(x)) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) # 数据通过末了一层,分类任务,常日会用softmax激活函数 x = self.softmax(x) return x # 定义输入层、隐蔽层和输出层的大小 input_size = 784 hidden_size1 = 16 hidden_size2 = 16 output_size = 10 # 分类任务,则设置为类别的数量 # 实例化模型 model = MyNet(input_size, hidden_size1, hidden_size2, output_size) # 打印模型构造 print(model)torch.nn.Sequentia

torch.nn.Sequential是一个Sequential容器,模块将按照布局函数中通报的顺序添加到模块中,也可以传入一个有序模块。

编程练习一下:

利用Sequential搭建了网络架构,个中先将图片进行展平(nn.Flatten)然后传入线形层,在经由relu激活函数,末了利用Linear进行输出。
须要把稳的是,torch.nn.Sequential不会自动在每层之间添加激活函数,以是我们须要将激活函数和线性层一起封装在nn.Sequential中。

import torch import torch.nn as nn import torch.nn.functional as F class MyNet(nn.Module): def __init__(self, input_size, hidden_size1, hidden_size2, output_size): super(MyNet, self).__init__() # 利用Sequential来定义层,个中包含了ReLU激活函数 self.layers = nn.Sequential( nn.Linear(input_size, hidden_size1), nn.ReLU(), nn.Linear(hidden_size1, hidden_size2), nn.ReLU(), nn.Linear(hidden_size2, output_size), ) def forward(self, x): # 数据通过Sequential定义的层 x = self.layers(x) return x # 定义输入层、隐蔽层和输出层的大小 input_size = 784 hidden_size1 = 16 hidden_size2 = 16 output_size = 10 # 实例化模型 model =MyNet(input_size, hidden_size1, hidden_size2, output_size) # 打印模型构造 print(model)

请把稳,这个模型并没有包含softmax层或对数概率层。
这是由于对付分类任务,我们常日在丢失函数中处理softmax(如利用nn.CrossEntropyLoss,我们不才一章中进行学习),它会内部打算softmax。

模型的代码是不是很大略?

在实际事情中,大概大部分韶光都在数据预处理中,所有生物信息学、基因组学、蛋白质组学等根本课程的学习与复习非常主要。

思考:到现在为止,我们构建的神经网络可以学习吗?

推举阅读涌井良幸, 涌井贞美.深度学习的数学[M]. 北京:公民邮政出版社,2019斋藤康毅.深度学习入门-基于Python的理论与实现[M].北京:公民邮电出版社,2018.Goodfellow 等.深度学习[M].北京:公民邮电出版社,2017.邱锡鹏.神经网络与深度学习[M].北京:机器工业出版社,2020尼克.人工智能简史[M]. 北京:公民邮政出版社,2017.