AI学习笔记(九)从零开始训练神经网络、深度学习开源框架

AI学习笔记之从零开始训练神经网络、深度学习开源框架

  • 从零开始训练神经网络
    • 构建网络的基本框架
    • 启动训练网络并测试数据
  • 深度学习开源框架
    • 深度学习框架
    • 组件--张量
    • 组件--基于张量的各种操作
    • 组件--计算图
    • 组件--自动微分工具
    • 组件--拓展包
    • 主流深度学习框架
      • 较为熟知的深度学习框架
      • 深度学习框架的标准化--ONNX
      • 本土深度学习框架
      • Tensorflow
      • pytorch
        • pytorch的优势
        • 常用工具包
        • Torch之Tensor
        • Torch之常见接口
        • Torch之自动求导
        • Torch之神经网络

从零开始训练神经网络

构建网络的基本框架

基本框架必须至少要留三个接口,分别完成如下功能:
1、初始化initialization,设置输入层,中间层,和输出层的节点数
2、训练train:根据训练数据不断的更新权重值
3、查询query:把新的数据输入给神经网络,网络计算后输出答案。(推理)
完成以上代码后,神经网络的大体框架就完成了,最重要的train函数,也就是通过训练样本训练链路权重的流程如下:
1、计算输入训练数据,给出网络的计算结果,根query()功能类似;
2、将计算结果与正确结果相对比,获取误差,采用误差方向传播更新网络里的每条链路权重。训练需要将数据进行预处理即归一化。

启动训练网络并测试数据

网络的最终目标是,输入一张手写数字图片后,网络输出该图片对应的数字。
由于网络需要0-9一共10个数字中挑选一个,于是网络的最终输出层应该有10个节点,每个节点对应一个数字。
假设图片对应的数字是0,那么输出层网络中,第一个节点应该输出一个高百分比,其他节点输出低百分比,如果图片对应的数字是9,那么输出层最后一个节点应该输出百分比,其他节点输出低百分比。
下面为利用numpy构建网络对数字进行识别的例子:

import numpy as np
import scipy.special as ss


class NeuralNetWork:
    def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
        # 初始化网络,设置输入层,中间层和输出层节点数
        self.in_nodes = input_nodes
        self.h_nodes = hidden_nodes
        self.o_nodes = output_nodes
        self.lr = learning_rate

        '''
        初始化权重矩阵,我们有两个权重矩阵,一个是wih表示输入层和中间层节点间链路权重形成的矩阵
        一个who,表示中间层和输出层间链路权重形成的矩阵
        '''
        self.wih = (np.random.normal(0.0, pow(self.h_nodes, -0.5), (self.h_nodes, self.in_nodes)))
        print('wih.shape', self.wih.shape)
        self.who = (np.random.normal(0.0, pow(self.o_nodes, -0.5), (self.o_nodes, self.h_nodes)))
        print('who.shape', self.who.shape)

        '''
        每个节点执行激活函数,得到的结果将作为信号输出到下一层,我们用sigmod作为激活函数
        '''
        self.activation_function = lambda x: (ss.expit(x))
        pass

    def train(self, inputs_list, targets_list):
        # 根据输入的训练数据更新节点链路权重
        """
        把input_list, target_list转换成numpy支撑的二维数组矩阵
        .T表示做矩阵的转置
        """
        inputs = np.array(inputs_list, ndmin=2).T
        targets = np.array(targets_list, ndmin=2).T
        # 计算信号经过输入层后产生的信号量
        hidden_inputs = np.dot(self.wih, inputs)
        # 中间层神经元对输入的信号做激活函数后得到输出信号
        hidden_outputs = self.activation_function(hidden_inputs)
        # 输出层接受来自中间层的信号量
        final_inputs = np.dot(self.who, hidden_outputs)
        # 输出层对信号量进行激活函数后得到最终输出信号
        final_outputs = self.activation_function(final_inputs)

        # 计算误差
        output_erros = targets - final_outputs
        hidden_erros = np.dot(self.who.T, output_erros)
        # 根据误差计算链路权重的更新量,然后把更新加到原来链路权重上
        self.who += self.lr * np.dot((output_erros * final_outputs * (1 - final_outputs)), np.transpose(hidden_outputs))
        self.wih += self.lr * np.dot((hidden_erros * hidden_outputs * (1 - hidden_outputs)), np.transpose(inputs))
        pass

    def query(self, inputs):
        # 根据输入数据计算并输出答案
        # 计算中间层从输入层接收到的信号量
        hidden_inputs = np.dot(self.wih, inputs)
        # 计算中间层经过激活函数后形成的输出信号量
        hidden_outputs = self.activation_function(hidden_inputs)
        # 计算最外层接收到的信号量
        final_inputs = np.dot(self.who, hidden_outputs)
        # 计算最外层神经元经过激活函数后输出的信号量
        final_outputs = self.activation_function(final_inputs)
        print(final_outputs)
        return final_outputs


"""
初始化神经网络
由于一张图片总共有28*28 = 784个数值,因此我们需要让网络的输入层具备784个输入节点
"""
input_nodes = 784
hidden_nodes = 250
output_nodes = 10
learning_rate = 0.1
n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)

# 读入训练数据
# open函数里的路径根据数据存储的路径来设定
training_data_file = open("dataset/mnist_train.csv", 'r')
training_data_list = training_data_file.readlines()
training_data_file.close()

# 加入epros,设定网络训练的循环次数
epochs = 5
for e in range(epochs):
    # 把数据依靠‘,’区分,并分别读入
    for record in training_data_list:
        all_values = record.split(',')
        inputs = (np.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
        # 设置图片与数值的对应关系
        targets = np.zeros(output_nodes) + 0.01
        targets[int(all_values[0])] = 0.99
        n.train(inputs, targets)

test_data_file = open("dataset/mnist_test.csv")
test_data_list = test_data_file.readlines()
test_data_file.close()
scores = []
for record in test_data_list:
    all_values = record.split(',')
    correct_number = int(all_values[0])
    print("该图片对应的数字为:", correct_number)
    # 预处理数字图片
    inputs = (np.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01
    # 让网络判断图片对应的数字
    outputs = n.query(inputs)
    # 找到数值最大的神经元对应的编号
    label = np.argmax(outputs)
    print("k网络认为图片的数字是:", label)
    if label == correct_number:
        scores.append(1)
    else:
        scores.append(0)
print(scores)

# 计算图片判断的成功率
scores_array = np.asfarray(scores)
print("perfermance = ", scores_array.sum() / scores_array.size)

运行结果如下:

wih.shape (250, 784)
who.shape (10, 250)
该图片对应的数字为: 7
[0.02734891 0.00516509 0.0263424  0.03901613 0.00213951 0.02675381
 0.00322178 0.96380821 0.00262904 0.01713408]
k网络认为图片的数字是: 7
该图片对应的数字为: 2
[2.72293026e-01 1.10720980e-03 5.21502816e-01 2.03967904e-02
 3.24687546e-04 8.55715395e-02 1.78048469e-01 7.37403328e-03
 1.43943395e-02 5.76306013e-03]
k网络认为图片的数字是: 2
该图片对应的数字为: 1
[0.00316568 0.98454501 0.00833526 0.02076886 0.00581089 0.04755665
 0.0214054  0.00529113 0.00377047 0.01411046]
k网络认为图片的数字是: 1
该图片对应的数字为: 0
[0.83734505 0.01507631 0.02972417 0.00660067 0.00326925 0.01341043
 0.02683458 0.13011349 0.00195523 0.00322517]
k网络认为图片的数字是: 0
该图片对应的数字为: 4
[0.0031507  0.00614831 0.04230189 0.00689271 0.94265558 0.00458838
 0.00512389 0.17587051 0.05506735 0.0064268 ]
k网络认为图片的数字是: 4
该图片对应的数字为: 1
[0.00575656 0.99211784 0.00765375 0.01042032 0.0091707  0.01709519
 0.00260456 0.00778338 0.00202902 0.01403657]
k网络认为图片的数字是: 1
该图片对应的数字为: 4
[8.56971366e-04 7.07671105e-04 1.17099421e-02 1.04559612e-02
 1.48063831e-01 5.63967334e-02 3.20984052e-02 8.69745821e-03
 3.41694845e-02 7.71053410e-01]
k网络认为图片的数字是: 9
该图片对应的数字为: 9
[0.00078666 0.04067627 0.00354012 0.51783209 0.40492139 0.00444808
 0.03816017 0.02579015 0.00647002 0.02400119]
k网络认为图片的数字是: 3
该图片对应的数字为: 5
[2.80587703e-02 5.25478970e-01 1.86935798e-02 5.53680611e-05
 3.70214380e-01 9.57418192e-02 1.70166695e-02 4.33108490e-03
 8.71122958e-03 5.20924162e-04]
k网络认为图片的数字是: 1
该图片对应的数字为: 9
[0.01004303 0.01767234 0.0174311  0.00879003 0.1111463  0.00406186
 0.02197812 0.02736403 0.00462142 0.54908237]
k网络认为图片的数字是: 9
[1, 1, 1, 1, 1, 1, 0, 0, 0, 1]
perfermance =  0.7

深度学习开源框架

深度学习框架

深度学习跨更加,比如caffe、fensorflow这些深度学习的工具,简单来说就是库,编程时导入后即可使用。其通常包括常用的深度学习组件如张量(Tensor)、基于张量的各种操作(Operation)、计算图(Computation Graph)、自动微分(Automatic Differentiation)工具、BLAS、cuBLAS、cuDNN等扩展包。

组件–张量

张量是所有深度学习框架最核心的组件,因为后续的所有运算和优化算法都是基于张量进行的。几何代数中定义的张量是基于向量和矩阵的推广,可以将标量视为零阶张量,矢量视为一阶张量,那么矩阵就是二阶张量。
将这一定义进行扩展,可以用四阶张量表示一个包含多张图片的数据集,其中的四个维度分别是:图片在数据集中的变号,图片高度、宽度,以及色彩数据。[N,H,W,C]
其优势在于将各种各样的数据抽象成张量表示,我们再输入神经网络模型进行后续处理是一种非常必要且高效的策略。因为如果没有这一步骤,我们就需要根据各种不同类型的数据组成形式定义各种不同类型的数据操作,更关键的是,当数据处理完后,也可以方便地将张量再转换会想要的格式。

组件–基于张量的各种操作

  • 有了张量以后,下一步就是一系列针对这一对象的数学运算和处理过程’;
  • 其实,整个神经网络都可以简单视为为了达到某种目的,针对输入张量进行一系列操作过程。而所谓“学习”就是不断纠正神经网络的实际输出结果和预期结果之间误差的过程。
  • 这里的一系列操作包含的范围很宽,可以使简单的矩阵乘法,也可以是卷积、池化和LSTM等较为复杂的运算。而且个框架支持的张量操作通常也不尽相同。

组件–计算图

  • 有了张量和基于张量的各种操作之后,接下来便需要将各种操作整合起来,输出想要的结果。
  • 但不幸的是,随着操作种类和数量的增多,管理起来就变得十分困难,各操作之间的关系变得比较难以清理,有可能引发各种意想不到的问题,包括多个操作之间应该不行还是顺次执行,如何协同各种不同的底层设备,以及如何避免各种类型的冗余操作等等。这些问题有可能拉低整个深度学习的运行效率或者引入不必要的bug,而计算图正式为解决这一问题产生的。
  • 将计算图作为前后端的中间表示(Intermediate Representations)可以带来良好的交互性。可以将Tensor对象视为数据结构,函数/方法作为操作类型,将特定的操作类型应用于特定的数据结构,从而定义出类似MATLAB的强大建模语言。
  • 因为计算图的引入,开发者得意从宏观上俯瞰整个神经网络的内部结构,就好像编译器可以从整个代码角度决定如何分配寄存器那样,计算图也可以从宏观上决定代码运行时的GPU内存分配,以及分布环境中不同底层设备间的相互写作方式。除此之外,现在也有许多深度学习框架将计算图应用于模型调试,可以随时输出当前某一操作类型的文本描述。
    AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第1张图片

组件–自动微分工具

  • 计算图带来的另一个好处是让模型训练阶段的梯度计算变得模块化且更为便捷,也就是自动微分法。
  • 将神经网络视为由多个现行过程组成的一个复杂的函数体,耳机算图则以模块化的方式完整表征了这一函数体的内部逻辑关系,因此微分这一复杂函数体,即求取模型梯度的方法就变成了在计算图中简单地从输入到输出进行一次完整遍历的过程。

组件–拓展包

  • 此前的大部分实现都是基于高级语言的(如jave、pyhton、lua等),而即使是执行最简单的操作,高级语言也会比低级语言消耗更多的CPU周期,更何况是结构复杂的深度神经网络,因此运算缓慢就成了高级语言的一个天然的缺陷;
  • 由于低级语言的最优化变成难度很高,而且大部分的基础曹组其实也都是公有的最优解决方案,因此一个显著的加速手段就是利用现成的扩展包。

主流深度学习框架

AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第2张图片
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第3张图片

较为熟知的深度学习框架

1、Tensorflow,前端框架Keras,背后巨头Google
2、PyTorch,前端框架FastAI,背后巨头Facebook
3、MXNet,前段框架Gluon,背后巨头Amazon
4、Cognitive Toolkit(CNTK),前端框架Keras或Gluon,背后巨头Microsoft

深度学习框架的标准化–ONNX

  • 开放神经网络交换(ONNX,“Open Neural Network Exchange”):
    ONNX最初由微软和Facebook联合发布,后来亚马逊也加入了进来,并发布了V1版本,宣布支持ONNX的公司还有AMD、ARM、华为、IBM、Intel、Qualcomm等
  • ONNX是一个表示深度学习模型的开放格式。它使用户可以更轻松地在不同框架之间转移模型,例如,他允许用户构建一个PyTorch模型,然后使用MXnet运行该模型来进行推理。

本土深度学习框架

1、华为MindSpore:支持端、边、云独立和协同的统一训练和推理训练。2020年3月28日,正式开源
2、百度PaddlePaddle:PaddlePaddle 100%都在Github上公开,没有内部版本。PaddlePaddle能够用于自然语言处理、图像识别、推荐引擎等多个领域,其优势在于开放的多个领先的预训练中文模型。
3、阿里巴巴(X-Deep Learning):阿里妈妈将其应用于自身广告业务的算法框架XDL(X-Deep Learning)进行开源。XDL主要是针对特定应用场景如广告的深度学习问题的解决方案,是上层高级API框架而不是底层框架。XDL需要财通桥接的方式配合使用Tensorflow和MXNet作为单节点的计算后端,XDL依赖于阿里提供特定的部署环境。
4、小米MACE:它针对移动芯片特性进行了大量优化,目前小米手机上已广泛应用,如人像模式、场景识别等。该框架用于Caffe2类似的描述文件定义模型,因此他能非常便捷地部署移动端应用。目前该框架为Tensorflow和Caffe模型提供转换工具,并且其他框架定义的模型很快也能得到支持。

Tensorflow

Tensorflow-1是一个采用数据流图(data flow graph),用于数值计算的开源软件库。节点在图中表示数学操作,图中的线(edges)则表示节点间相互联系的多维数据数组,即张量(tensor)。它灵活的框架可以在多种平台上展开计算,例如台式计算机中的一个或多个CPU、GPU),服务器,移动设备等。其官网地址:https://www.tensorflow.org/
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第4张图片
如下为用tensorflow对随机生成的离散点进行拟合的示例代码:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# 使用numpy生成200个随机点
x_data = np.linspace(-0.5, 0.5, 200)[:, np.newaxis]
noise = np.random.normal(0, 0.02, x_data.shape)
y_data = np.square(x_data) + noise

# 定义两个placeholder存放输入数据
x = tf.placeholder(tf.float32, [None, 1])
y = tf.placeholder(tf.float32, [None, 1])

# 定义神经网络中间层
Weights_L1 = tf.Variable(tf.random_normal([1, 10]))
biases_L1 = tf.Variable(tf.zeros([1, 10]))
Wx_plus_b_L1 = tf.matmul(x, Weights_L1) + biases_L1
L1 = tf.nn.tanh(Wx_plus_b_L1)

# 定义神经网络输出层
Weights_L2 = tf.Variable(tf.random_normal([10, 1]))
biases_L2 = tf.Variable(tf.zeros([1, 1]))
Wx_plus_b_L2 = tf.matmul(L1, Weights_L2) + biases_L2
prediction = tf.nn.tanh(Wx_plus_b_L2)

# 定义损失函数
loss = tf.reduce_mean(tf.square(y-prediction))
# 定义方向传播算法(使用梯度下降算法训练)
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

with tf.Session() as sess:
    # 变量初始化
    sess.run(tf.global_variables_initializer())
    # 训练2000次
    for i in range(2000):
        sess.run(train_step, feed_dict={x:x_data, y:y_data})

    # 获得预测值
    prediction_value = sess.run(prediction, feed_dict={x:x_data})

    # 画图
    plt.figure()
    plt.scatter(x_data, y_data, label='act data')  # 散点是真实值
    plt.plot(x_data, prediction_value, 'r-', lw=5, label='predict curve')  # 曲线是预测值
    plt.legend(loc='best')
    plt.show()

运行结果如下:
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第5张图片
下面为用keras对mnist数据集进行训练识别示例代码:

rom tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt
from tensorflow.keras import models
from tensorflow.keras import layers
from tensorflow.keras.utils import to_categorical

'''
将训练数据和检测数据加载到内存中(第一次运行需要下载数据,会比较慢):
train_images:用于训练系统的手写数字图片
train_labels:用于标注图片的信息
test_images:用于检测系统训练效果的图片
test_labels:test_images图片对应的数字标签=
'''
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print('train_images.shape = ', train_images.shape)
print('train_labels = ', train_labels)
print('test_images.shape = ', test_images.shape)
print('test_labels = ', test_labels)
'''
1.train_images.shape打印结果表明,train_images是一个含有60000个元素的数组.
数组中的元素是一个二维数组,二维数组的行和列都是28.
也就是说,一个数字图片的大小是28*28.
2.train_lables打印结果表明,第一张手写数字图片的内容是数字5,第二张图片是数字0,以此类推.
3.test_images.shape的打印结果表示,用于检验训练效果的图片有10000张。
4.test_labels输出结果表明,用于检测的第一张图片内容是数字7,第二张是数字2,依次类推。
'''

'''
使用tensorflow.Keras搭建一个有效识别图案的神经网络,
1.layers:表示神经网络中的一个数据处理层。(dense:全连接层)
2.models.Sequential():表示把每一个数据处理层串联起来.
3.layers.Dense(…):构造一个数据处理层。
4.input_shape(28*28,):表示当前处理层接收的数据格式必须是长和宽都是28的二维数组,
后面的“,“表示数组里面的每一个元素到底包含多少个数字都没有关系.
'''
network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
network.add(layers.Dense(10, activation='softmax'))  #softmax将输出映射到【0,1】之内
network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

'''
在把数据输入到网络模型之前,把数据做归一化处理:
1.reshape(60000, 28*28):train_images数组原来含有60000个元素,每个元素是一个28行,28列的二维数组,
现在把每个二维数组转变为一个含有28*28个元素的一维数组.
2.由于数字图案是一个灰度图,图片中每个像素点值的大小范围在0到255之间.
3.train_images.astype(“float32”)/255 把每个像素点的值从范围0-255转变为范围在0-1之间的浮点值。
'''
train_images = train_images.reshape((60000, 28*28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28*28))
test_images = test_images.astype('float32') / 255

'''
把图片对应的标记也做一个更改
目前所有图片的数字图案对应的是0到9
例如test_images[0]对应的数字是7的手写图案,那么其对对应的标记test_labels[0]的值就是7
我们需要把数值7编程一个含有10个元素的数组,然后在第7个元素设置为1,其他元素设置为0
例如test_labels[0]的值由7转变为数组[0, 0, 0, 0, 0, 0, 0, 1, 0 ,0]
'''
print("before change", test_labels[0])
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
print("after change", test_labels[0])

'''
把数据输入网络进行训练:
train_images:用于训练的手写数字图片
train_labels:对应的是图片的标记
batch_size:每次网络从输入的图片数组中随机选取128个作为一组进行计算
epochs:每次计算的循环是5次
verbose: 0:不输出日志信息;1:输出进度条信息 2:每个epoch只输出一条记录
'''
network.fit(train_images, train_labels, epochs=5, batch_size=128, verbose=2)

'''
测试数据输入,检验网络学习后的图片识别效果
识别效果与硬件有关(CPU/GPU).
verbose: 0:不输出日志信息;1:输出进度条信息
'''
test_loss, test_acc = network.evaluate(test_images, test_labels, verbose=1)
print('test_loss = ', test_loss)
print('test_acc = ', test_acc)

'''
输入一张手写数字图片到网络中,看看它的识别效果
'''
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
digit = test_images[1]
plt.imshow(digit, cmap=plt.cm.binary)
test_images = test_images.reshape((10000, 28*28))
res = network.predict(test_images)
predict = -1
for i in range(res[1].shape[0]):
    if 1 == res[1][i]:
        predict = i
        break
plt.title('predict_num is:' + str(predict))
plt.show()

运行结果如下:

train_images.shape =  (60000, 28, 28)
train_labels =  [5 0 4 ... 5 6 8]
test_images.shape =  (10000, 28, 28)
test_labels =  [7 2 1 ... 4 5 6]
before change 7
after change [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]

Epoch 1/5
 - 4s - loss: 0.2570 - acc: 0.9251
Epoch 2/5
 - 4s - loss: 0.1036 - acc: 0.9698
Epoch 3/5
 - 4s - loss: 0.0677 - acc: 0.9793
Epoch 4/5
 - 4s - loss: 0.0496 - acc: 0.9849
Epoch 5/5
 - 4s - loss: 0.0374 - acc: 0.9890
 
    32/10000 [..............................] - ETA: 22s
  864/10000 [=>............................] - ETA: 1s 
 1760/10000 [====>.........................] - ETA: 0s
 2720/10000 [=======>......................] - ETA: 0s
 3712/10000 [==========>...................] - ETA: 0s
 4672/10000 [=============>................] - ETA: 0s
 5664/10000 [===============>..............] - ETA: 0s
 6656/10000 [==================>...........] - ETA: 0s
 7648/10000 [=====================>........] - ETA: 0s
 8640/10000 [========================>.....] - ETA: 0s
 9632/10000 [===========================>..] - ETA: 0s
10000/10000 [==============================] - 1s 60us/step
test_loss =  0.0682341940671904
test_acc =  0.9793

AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第6张图片

pytorch

官方网站为:https://pytorch.org/

  • pytorch是torch的python版本,是由facebook开源的神经网络架构,专门针对GPU加速的深度神经网络(DNN)编程。Torch是一个经典的对多为主句进行操作的张量(Tensor)库,在机器学习和其他数学密集型应用有管饭应用。
  • Pytorch计算图是动态的,可以根据计算需要实时改变计算图
  • 由于Torch语言采用lua,导致国内一直很小众,并逐渐被Python的Tensorflow抢走用户。作为经典机器学习库Torch的端口,Pytorch为Python语言提供了舒适的写代码选择。
  • 其旨在服务两类场合:1)代替numpy发挥GPU潜能;2)一个提供了高灵活度和效率的深度学习实验性平台。

pytorch的优势

1、简洁,Pytorch的设计最求最少的封装,尽量避免重复造轮子,Pytorch的设计遵循tensor->variable(autograd)->nn,Module三个由低到高的抽象层次,分别代表高维数组(张量)、自动求导(变量)和神经网络(层/模块),而且这三个抽象之间联系金币,可以同时进行修改和操作。
2、速度,pytorch的灵活性并未导致速度的降低;
3、易用,PyTorch是所有框架中面向对象的接口来源于Torch,比较灵活
4、活跃的社区,Pytorch提供了完整的文档,循序渐进的指南

常用工具包

1、torch:类似于Numpy的张量库,支持GPU;
2、torch.autograd:基于type的自动区别库,支持torch之中的所有可区分张量运行;
3、torch.nn:为最大化灵活性而设计,与autograd深度整合的神经网络库
4、torch.optim:与torch.nn一起使用的优化包,包含SGD、RMSProp、LBFGS、Adam等标准优化方式;
5、torch.multiprocessing:python多进程并发,进程之间torch Tensors的内存共享;
6、torch.utils:数据载入器。具有训练器和其他便利功能;
7、torch.legacy(.nn/.optim):出于后向兼容性考虑,从Torch移植来的legacy代码;
理解pytorch的基础主要从以下三个方面:
1、Numpy风格的Tensor操作。pytorch中的tensor提供的API参考了Numpy的设计;
2、变量自动求导。在一序列计算过程形成的计算图中,参与的变量可以方便地计算子集对目标函数的梯度。
3、神经网络与算是函数优化等高层封装。网络层的封装存在torch.nn模块,损失函数由torch.nn.functional模块提供,优化函数由torch.optim模块提供。
特备注意
通道问题:不同的视觉库对于图像读取的方式不一样,图像的通道数不一样;
opencv的默认imread就是HWC,PyTorch的Tensor为CHW,Tensroflow两者都支持。

Torch之Tensor

Torch定义了七种CPU tensor和八种GPU tensor类型:
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第7张图片
Tensor对象的方法:
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第8张图片

Torch之常见接口

AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第9张图片

Torch之自动求导

tensor对象通过一系列的运算可以组成动态图,对于每个tensor对象,有下面几个变量控制求导的属性:
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第10张图片

Torch之神经网络

下面表格中列出了比较重要的神经网络层组件。对应的在nn.functional模块中,提供这些层对应的函数实现。通常对于可训练参数的层使用module,而对于不需要训练的层如softmax这些,可以使用functional中的函数。
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第11张图片
AI学习笔记(九)从零开始训练神经网络、深度学习开源框架_第12张图片

  • torch.nn.Module提供了神经网络的基类,当实现神经网络时需要继承自此模块,并在初始化函数中创建网络需要包含的层,并实现forward函数完成前向计算,网络的反响计算会由自动求导机制处理;
  • 通常将需要训练的层在init函数中,将参数不需要训练的层在forward方法里调用对应的函数来实现相应的层。
  • 在pytorch中常见步骤1)写好网络;2)编写数据的标签和路径索引;3)把数据送到网络

你可能感兴趣的:(AI,python)