2019-03-04 17:25:11 qq_41997920 阅读数 392
  • 笔记式Python基础入门

    您观看课程学习后 免费入群领取【超全Python资料包+17本学习电子书】 课程简介:以笔记为导向作为讲解内容是本人一贯的授课亮点,一条笔记包含一个知识点,本课程450多条笔记涵盖了python所有入门知识点,非常适合作为入门课程。

    2076 人正在学习 去看看 翁老师

带着问题学习深度学习,罗列深度学习中一些基础问题,并在学习中一点一点解决并理解相关问题。

同时在此特别感谢Doctor Liu的指导!

以下涉及问题的答案可能来源于网络或者论文,以及书籍,如有侵权请联系删除。

(一)深度学习/神经网络

1.神经网络常用的激活函数有哪些?(五种以上)目前最常用的有哪些?

ans:sigmoid函数,tanh函数,ReLU函数 ,Leaky ReLU函数, Maxout函数, ELU函数这里写图片描述

2.为什么要引入激活函数?

ans: 在神经网络中,我们经常可以看到对于某一个隐藏层的节点,该节点的激活值计算一般分为两步:
    在进入这个隐藏节点后,会先进行一个线性变换,计算出值 z[1],再进行一个非线性变换,也就是经过非线性激活函数.

3.常用的损失函数有哪些?都用在什么任务上?

ans:损失函数是指用于计算标签和预测值之间的差异

         binary_crossentropy,二分类问题,多分类,多标签问题;

         categorical_crossentroy,多分类,单标签问题; 

         mse,回归到任意值;

         mse,binary_crossentropy,回归到0-1范围的值;

         BCELoss,二分类用的交叉熵

4.为什么要设置学习率衰减?常用的学习率衰减方式有哪些?

 ans:我们平衡模型的训练速度和损失(loss)后选择了相对合适的学习率(learning rate),但是训练集的损失下降到一定的程度后就不在下降了,遇到这种情况通常可以通过适当降低学习率(learning rate)来实现。但是,降低学习率又会延长训练所需的时间。学习率衰减(learning rate decay)就是一种可以平衡这两者之间矛盾的解决方案。学习率衰减的基本思想是:学习率随着训练的进行逐渐衰减。学习率衰减基本有两种实现方法:

  1. 线性衰减。例如:每过5个epochs学习率减半
  2. 指数衰减。例如:每过5个epochs将学习率乘以0.1

5.常用的梯度下降优化算法有哪些? 

ans:小批量随机梯度下降;真SGD,Adagrad,RMSprop,带动量的随机梯度下降Momentum,Adam

6.什么是分类任务?什么是回归任务?神经网络如何用于这两类任务上?

 ans:

  • 分类是预测离散类标签输出的问题。
  • 回归是预测连续数量输出的问题。

分类预测建模是将映射函数(f)从输入变量(x)逼近到离散输出变量(y)的任务。输出变量通常称为标签或类别。映射函数预测给定观测值的类或类别,分类模型通常将连续值预测为属于每个输出类别的给定示例的概率。 概率可以被解释为属于每个类别的给定例子的可能性或置信度。 可以通过选择具有最高概率的类别标签将预测概率转换为类别值。

回归预测建模是将输入变量(X)映射到连续输出变量(y)的映射函数(f)的任务。连续输出变量是一个实数值,例如整数或浮点值。 这些往往是数量,如金额和大小。

  • 回归问题需要预测数量。
  • 回归可以具有实值或离散的输入变量。
  • 多输入变量的问题通常称为多元回归问题。
  • 输入变量按时间排序的回归问题称为时间序列预测问题。

由于回归预测模型预测一个数量,所以该模型的技巧必须作为这些预测中的一个误差来报告。

7.什么是batch normalization?

ans: 批标准化, 和普通的数据标准化类似, 是将分散的数据统一的一种做法, 也是优化神经网络的一种方法.核心思想是标准化这个过程是可微的,减少不合理的初始化问题,对很坏单独初始化有很强的鲁棒性,同时可以加快网络的手链速度。还可以理解微在网络的每一层前面都会做数据的预处理。

(为什么Batch Normalization那么有用?https://zhuanlan.zhihu.com/p/5274928

(batch normalization 详解 https://blog.csdn.net/gbyy42299/article/details/80363332

8.常用的权重初始化方法有哪些?

因为权重是一个Variable,所以只需要提取其中的data属性,在进行所需要的处理即可。 

  • Xavier初始化,uniform形式,normal形式;
  • MSRA,uniform形式,normal形式;
  • Gaussian

(二)卷积神经网络

1.卷积神经网络中的卷积是什么意思?为什么要使用卷积?

ans:参数共享稀疏连接平移不变

深层神经网络中使用卷积,可以通过参数共享和稀疏连接,减少参数。参数少了,我们就能用更少的训练集来训练网络,从而预防过拟合。

  • 卷积层只需要很少的参数,就能连接两个很大维度的特征
  • 全连接层,要连接两个很大维度的特征,参数会非常多
  • 有Pooling层的存在,神经网络具备平移不变这样的性质,提高了泛化能力。
     

2.卷积神经网络与全连接神经网络有什么区别和联系?

ans:相似之处,都是由一些神经元构成,神经元中包含需要学习的参数,通过网络的输入,最后输出结果,通过损失函数优化网络中的参数。

  1. 不同之处:网络的层结构不同,全连接神经网络由一系列的隐藏层组成,每个隐藏层由若干个神经元构成,每个神经元与前一层的神经元相关联,但每一层的神经元却是独立的,这样会导致权重的数目激增;卷积神经网络是一个3D容量的神经元,通过宽度,高度,深度排列。

3.请解释什么是:(1)卷积核(2)卷积核大小(3)卷积步长(4)feature map(5)padding(6)pooling

ans:

  • 卷积核:“模板窗口”每移动到一个位置,就和图片中的对应元素进行一次卷积运算,注意我们一般把“模板窗口”称为卷积核。特征向量集,提取特征
  • 卷积核大小:滤波器的尺寸?3D的权重集合称之为卷积核(参数共享为什么有效是因为:一个特征在不同位置的表现是相同的)
  • 卷积步长:卷积步长是指过滤器在图像上滑动的距离;
  • feature map:在每个卷积层,数据都是以三维形式存在的。你可以把它看成许多个二维图片叠在一起,其中每一个称为一个feature map;
  • padding:通过一个3*3的过滤器来对6*6的图像进行卷积,得到了一幅4*4的图像,假设输出图像大小为n*n与过滤器大小为f*f,输出图像大小则为(n−f+1)∗(n−f+1)(n−f+1)∗(n−f+1)。 这样做卷积运算的缺点是,卷积图像的大小会不断缩小,另外图像的左上角的元素只被一个输出所使用,所以在图像边缘的像素在输出中采用较少,也就意味着你丢掉了很多图像边缘的信息,为了解决这两个问题,就引入了padding操作,也就是在图像卷积操作之前,沿着图像边缘用0进行图像填充。对于3*3的过滤器,我们填充宽度为1时,就可以保证输出图像和输入图像一样大;
  • pooling:池化层,降低数据体的空间的大小;

4.pooling的方式有哪些?目前常用的是什么?

ans:

  • Max Pooling Over Time操作
  • K-Max Pooling
  • Chunk-Max Pooling

(目前只用过Maxpool2d)

5.如何计算卷积后的feature map的大小?

ans:

像素宽度:W(Width)

填充大小:P(Padding)

卷积核大小:K(Kernel-size)

步长大小:S(stride)

卷积后所得feature map尺寸大小计算公式如下:

W_{n+1}=\left (W_{n}+2*P-K \right )/S+1

6.目前常见的卷积神经网络模型有哪些?请对比他们的异同(以imageNet竞赛的冠军模型为例)

ans:

  • LeNet
  • AlexNet
  • GoogleNet
  • ResNet

异同点:更深吧!

7.什么叫端到端学习?

ans:从输入端(输入数据)到输出端会得到一个预测结果,与真实结果相比较会得到一个误差,这个误差会在模型中的每一层传递(反向传播),每一层的表示都会根据这个误差来做调整,直到模型收敛或达到预期的效果才结束,这是端到端的。

8.用卷积神经网络对图片进行分类和用SVM有什么区别?

ans:神经网络是端到端的训练,不需要人工标注,svm一般需要预先设计和提取特征。

 

(三)深度学习之pytorch学习

1.如何查看pytorch版本?

import torch
print(torch.__version__)  #注意是双下划线

2.如何查看当前pytorch环境是否支持GPU运算?

torch.cuda.is_available()

 

3.numpy array和pytorch variable如何相互转化?

ans:

1 tensor 转 numpy

a = torch.FloatTensor(3,3)
print a.numpy()


2 numpy 转 tensor
 

a = np.ones(5)
torch.from_numpy(a)


3 Variable 转 numpy

a = Variable(torch.FloatTensor(3,3))
print a.data.numpy()


4 numpy 转  Variable

a = np.ones(5)
print Variable(torch.from_numpy(a))


 

4.如何查看一个varible(tensor)是否会被求导?如何设置一个variable(tensor)是否被求导?

ans:

5.请解释以下类的初始化参数及用法:

(1)  torch.nn.Conv2d(in_channels,out_channels,kernel_size,stride=1,padding=0,dilation=1,groups=1,bias=True)

ans:Conv2d:二维卷积 ;

         in_channels:输入数据体的深度;

         out_channels:输出数据体的深度;

         kernel_size:卷积核大小; 

         stride=1:步长;

         padding=x:表示周围进行x个像素的填充

         dilation=1:表示卷积对输入空间的间隔,默认dilation=1;

         groups=1:输入输出数据体深度上的联系,默认groups=1;

         bias=True:布尔值,默认bias=True,也表偏执;

(2)  torch.nn.MaxPool2d(kernel_size,stride=None,padding=0,dilation=1,return_indices=False,ceil_mode=False)

ans: MaxPool2d:二维最大池化层;

           return_indices=False:表示是否返回最大值所处的下标,默认return_indices=False;

           ceil_mode=False:默认ceil_mode=False       

(3)  torch.nn.linear(in_features,out_feature,bias=Ture)

ans:torch.nn.Linear类用于定义模型的线性层,即完成前面提到的不同的层之间的线性变换;

          in_features:输入特征数;

          out_feature:输出特征数。

 

 

 

 

 

 

 

 

 

2019-07-16 03:17:42 kinO_o 阅读数 36
  • 笔记式Python基础入门

    您观看课程学习后 免费入群领取【超全Python资料包+17本学习电子书】 课程简介:以笔记为导向作为讲解内容是本人一贯的授课亮点,一条笔记包含一个知识点,本课程450多条笔记涵盖了python所有入门知识点,非常适合作为入门课程。

    2076 人正在学习 去看看 翁老师

深度学习笔记【1】

从零开始的搭建神经网络之路

序言#

鸽了朋友能有两天,终于开始写第一篇博客。也是从今天开始吧,我会定期更新我的关于深度学习的博客,现在由于自己的网站备案还没好,就暂时先更新在这儿了。

本篇是该系列的开头之作,鉴于对深度学习领域真的知之甚少,就找了些前辈的东西来入门。本文主要参考的是Victor Zhou先生的博文,以及我的一位朋友的博文,在此对二位表示感谢,文末我会附上参考博文的链接。

现下我们所言的神经网路,一般都应该称之为人工神经网络或类神经网络,是模仿生物神经网络而来的计算模型。他被用于解决各种很难被传统的基于规则的编程所解决的问题。接下来待我一一讲来。

神经元#

神经元(Neuron)是神经网络的基石,一个神经元需要输入,输出,以及相应的计算.。

在这里插入图片描述

这是一个有两个输入的神经元,每一个输入都经过加权xix_i​*wiw_i​,然后求和(xiwi)+b(\sum x_i w_i )+b,最终通过激活函数输出。其中,具体的权值wiw_i我们是不知道的,这也是随后的学习算法的主要作用。

在加权求和的过程中,为何要将求和结果与偏置(bias)相加呢?其实是因为在生物神经网络中,神经元需要做够多的电位变化,亦即超过阈值,才会释放动作电位。在人工神经网络中也是如此,只有当你神经元的加权和大于某一阈值时,输出1,反之为0。而为了更好的计算和表达,我们将与阈值与加权和移到同一边,同时给之取名偏置 bias

神经元的python实现如下

class Neuron: #神经元
    def __init__(self, weights, bias):#初始化
        self.weights = weights #权重
        self.bias = bias  #偏置

在这里,没有涉及到计算的部分,此部分会在接下来实现

Activation函数#

这个函数就是用于约束神经元输出的。不知聪明的你有没有发现,我们之前的加权和的结果是无界的,即既可无穷大又可无穷小。所以我们必须将其约束在一个区间中(最终我们可将输出结果视作为概率),为此我们需要一个函数来实现。在这我们选用 sigmoid 函数。
在这里插入图片描述
sigmoid 函数的函数表达式为:

H(x)=11+exH(x)={1\over 1+e^{-x}}

其输出在(0,1)的范围内。
python 实现如下

def sigmoid(x):
	  return 1/(1+np.exp(-x))

至此,我们就可以将神经元的输出函数给写出来。

class Neuron:
	def _init_(self,weights,bias):
		self.weights=weights
		self.bias=bias
	def feedforward(self,inputs):
		total=np.dot(self,weights,inputs)+self.bias
		return sigmoid(total)

神经网络#
接下来我们就要试着搭建一个神经网络了。
比如说我们遇到这样一个问题:

Name Weight(Ib) Height Gender
Alice 133 65 F
Bob 160 72 M
Charlie 152 70 M
Diana 120 60 F

这儿有些数据,是关于四个人的身高体重以及性别。
现在,你能不能用神经网络来做一个简单的分类器,通过身高体重来判断这个人是男是女?
下面给出一个简单的神经网络模型:
在这里插入图片描述
这个模型由三个神经元组成,Hidden 层的神经元有两个输入一个输出,Output 层的有两个输入。最终,我们的输出是一个介于0和1之间的数值,在这儿,我们可将其认作是表示输入信息对应的人是男生的概率。

Loss Function#
现在输入输出的问题已经解决,但作为一个数学模型,我们还需要一定的手段检验模型的优劣。
在这里,我们选用一种常用的MSE(mean squared error)。
MSE=1ni=1n(ytrueypred)2MSE=\frac1n\sum_{i=1}^n (y_{true}-y_{pred})^2

MSEpython 实现如下

def mse_loss(y_true,y_pred):
	return ((y_true-y_pred)**2).mean()

Train#
至此,我们来到了神经网络的精髓部分,即通过训练调整权值和偏置。通过链式法则的推导,我们可以得到以下公式,其中 LLMSE 函数
Lwi=Lypred×ypredhi×hiwi\frac{\partial L}{\partial w_i}=\frac{\partial L}{\partial y_{pred}}×\frac{\partial y_{pred}}{\partial h_i}×\frac{\partial h_i}{\partial w_i}

具体推导过程,可参考文末链接博文

之后再根据数值分析中的梯度下降法,即
wiwiηLwiw_i\leftarrow w_i - \eta\frac{\partial L}{\partial w_i}
来调整相应参数,其中,η\eta称为学习效率,一般取较小正数。
具体的:

  • 若偏导数是正的,wiw_i要减小,以使LL减小;
  • 若偏导数是负的,wiw_i要增大,以使LL减小;

实现
不停地选择样例,计算LL,并调整权值和偏置,直至LL为0或很小。

全部代码如下

import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
    return 1/(1+np.exp(-x))
def deriv_sigmoid(x):
    fx=sigmoid(x)
    return fx*(1-fx)
def mse_loss(y_true,y_pred):
    return ((y_true-y_pred)**2).mean()
time=np.array(range(0,100))
lost=np.linspace(0,100,100)

class Neuron:
    def __init__(self,weights,bias):
        self.weights=weights
        self.bias=bias
    
    def feedforward(self,inputs):
        total=np.dot(self.weights,inputs)+self.bias
        return sigmoid(total)

class NeuralNetwork:
    def __init__(self):
        self.w1=np.random.normal()
        self.w2=np.random.normal()
        self.w3=np.random.normal()
        self.w4=np.random.normal()
        self.w5=np.random.normal()
        self.w6=np.random.normal()

        self.b1=np.random.normal()
        self.b2=np.random.normal()
        self.b3=np.random.normal()
    def feedforward(self,x):
        h1=sigmoid(self.w1*x[0]+self.w2*x[1]+self.b1)
        h2=sigmoid(self.w3*x[0]+self.w4*x[1]+self.b2)
        o1=sigmoid(self.w5*h1+self.w6*h2+self.b3)
        return o1
    def train(self,data,all_y_trues):
        learn_rate=0.1
        epochs=1000
        for epoch in range(epochs):
            for x,y_true in zip(data,all_y_trues):
                sum_h1=self.w1*x[0]+self.w2*x[1]+self.b1
                h1=sigmoid(sum_h1)
                sum_h2=self.w3*x[0]+self.w4*x[1]+self.b2
                h2=sigmoid(sum_h2)
                sum_o1=self.w5*h1+self.w6*h2+self.b3
                o1=sigmoid(sum_o1)
                y_pred=o1

                #下面计算偏导数,用于改变权值
                d_L_d_ypred=-2*(y_true-y_pred)

                d_ypred_d_w5=h1*deriv_sigmoid(sum_o1)
                d_ypred_d_w6=h2*deriv_sigmoid(sum_o1)
                d_ypred_d_b3=deriv_sigmoid(sum_o1)

                d_ypred_d_h1 = self.w5 * deriv_sigmoid(sum_o1)
                d_ypred_d_h2 = self.w6 * deriv_sigmoid(sum_o1)

                d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)
                d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)
                d_h1_d_b1 = deriv_sigmoid(sum_h1)


                d_h2_d_w3=x[0]*deriv_sigmoid(sum_h2)
                d_h2_d_w4=x[1]*deriv_sigmoid(sum_h2)
                d_h2_d_b2=deriv_sigmoid(sum_h2)

                #更新权值和偏置值
                #h1
                self.w1-=learn_rate*d_L_d_ypred*d_ypred_d_h1* d_h1_d_w1
                self.w2-=learn_rate*d_L_d_ypred*d_ypred_d_h1* d_h1_d_w2
                self.b1-=learn_rate*d_L_d_ypred*d_ypred_d_h1* d_h1_d_b1
                #h2
                self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w3
                self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w4
                self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_b2

                # Neuron o1
                self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_w5
                self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_w6
                self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3

                #计算损失函数
            if epoch % 10 == 0:
                    y_preds = np.apply_along_axis(self.feedforward, 1, data)
                    loss = mse_loss(all_y_trues, y_preds)
                    lost[epoch//10] = loss
                    print("Epoch %d loss: %.3f" % (epoch, loss))


data=np.array([
    [-2,-1],
    [25,6],
    [17,4],
    [-15,-6]
])
all_y_trues=np.array([
    1,
    0,
    0,
    1,
])
network=NeuralNetwork()
network.train(data,all_y_trues)
plt.plot(time,lost)
plt.show()

训练误差的趋势图,如下:
在这里插入图片描述
参考来源
Vctor Zhou先生的博文
好友链接


不想做个言而无信的人,再加之此事对我也很有帮助。当初就答应了朋友,再次真的十分感谢他,希望他不会嫌弃我吧!

2018-12-26 16:51:43 thu_yang 阅读数 72
  • 笔记式Python基础入门

    您观看课程学习后 免费入群领取【超全Python资料包+17本学习电子书】 课程简介:以笔记为导向作为讲解内容是本人一贯的授课亮点,一条笔记包含一个知识点,本课程450多条笔记涵盖了python所有入门知识点,非常适合作为入门课程。

    2076 人正在学习 去看看 翁老师

机器学习(深度学习)笔记@奔跑的Mir.Wang

第一节 Tensorflow运行环境的搭建

本章中主要记录的在windows7系统下,安装Anaconda、安装Tensorflow。

1、安装Anaconda

Anaconda 是一个用于科学计算的 Python 发行版,支持 Linux, Mac, Windows, 包含了众多流行的科学计算、数据分析的 Python 包。
由于Anaconda官方网站的软件下载速度比较慢,所以本文推荐使用清华开源镜像站的Anaconda软件包
Anaconda 安装包可以到 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 下载。
如下图,选择对应系统版本的Anaconda进行下载,本文中下载的是Anaconda3-5.1.0-Windows-x86_64

下载对应系统版本的Anaconda下载完成后,安装即可,安装过程和普通软件安装相同不在叙述。
安装完成后,如下图:
在开始菜单,所有程序可看到
2、安装Tensorflow
在windows系统下,由于目前tensorflow只支持Python3.5环境,所以需要创建一个python3.5的运行环境。
创建方式:可以通过Anaconda Navigator界面,点击按钮创建,也可以打开Anaconda Prompt输入命令创建
创建命令为:
conda create -n your_env_name python=3.5
创建虚拟环境完成后,激活Python3.5虚拟环境,在Anaconda Prompt输入:
activate your_env_name
在此虚拟环境中,安装tensorflow,输入命令:
pip install tensorflow
程序会自动安装tensorflow及其所依赖的包,至此tensorflow 安装完成。
在以后的学习开发过程中需要的包,均可以输入pip install 进行安装。

2018-05-10 21:36:15 u012950413 阅读数 1812
  • 笔记式Python基础入门

    您观看课程学习后 免费入群领取【超全Python资料包+17本学习电子书】 课程简介:以笔记为导向作为讲解内容是本人一贯的授课亮点,一条笔记包含一个知识点,本课程450多条笔记涵盖了python所有入门知识点,非常适合作为入门课程。

    2076 人正在学习 去看看 翁老师

实现一个手写数字识别的算法(使用神经网络算法)


MNIST数据集:

训练(train) 50,000
验证(validation) 10,000
测试(test) 10,000
#神经网络
class Network(object):
def __init__(self, sizes):
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        self.weights = [np.random.randn(y, x)
                        for x, y in zip(sizes[:-1], sizes[1:])]

sizes: 每层神经元的个数, 例如: 第一层2个神经元,第二层3个神经元:

                              net = Network([2, 3, 1]); 

np.random.rand(y, 1): 随机从正态分布(均值0, 方差1)中生成
net.weights[1]: 存储连接第二层和第三层的权重 (Python索引从0开始数)

α=σ(ωα+b)

正向传播


    def feedforward(self, a):
        """Return the output of the network if "a" is input."""
        for b, w in zip(self.biases, self.weights): zip函数把两个矩阵(实际上是多个维度不同的向量组成)组合
            a = sigmoid(np.dot(w, a)+b)
        return a

反向传播

随机梯度下降更新公式:

权重更新

wkwk=wkηCx/wk

偏向更新

blbl=blηCx/bl

#随机梯度下降算法
def SGD(self, training_data list形式, epochs, mini_batch_size 每次用于梯度下降的实例的大小, eta 学习率,
            test_data=None):
        """Train the neural network using mini-batch stochastic
        gradient descent.  The "training_data" is a list of tuples
        "(x 输入特征向量, y x数据所属label)" representing the training inputs and the desired
        outputs.  The other non-optional parameters are
        self-explanatory.  If "test_data" is provided then the
        network will be evaluated against the test data after each
        epoch, and partial progress printed out.  This is useful for
        tracking progress, but slows things down substantially."""
        if test_data: n_test = len(test_data)
        n = len(training_data)
        for j in xrange(epochs):
            random.shuffle(training_data)
            mini_batches = [
                training_data[k:k+mini_batch_size]
                for k in xrange(0, n, mini_batch_size)]
            for mini_batch in mini_batches:
                self.update_mini_batch(mini_batch, eta)
            if test_data:
                print "Epoch {0}: {1} / {2}".format(
                    j, self.evaluate(test_data), n_test)
            else:
                print "Epoch {0} complete".format(j)

# 反向传播代码
def update_mini_batch(self, mini_batch, eta):
    """Update the network's weights and biases by applying
    gradient descent using backpropagation to a single mini batch.
    The "mini_batch" is a list of tuples "(x, y)", and "eta"
    is the learning rate."""
    nabla_b = [np.zeros(b.shape) for b in self.biases]
    nabla_w = [np.zeros(w.shape) for w in self.weights]
    for x, y in mini_batch:
    # 调用backpropagation算法求出偏导数
        delta_nabla_b, delta_nabla_w = self.backprop(x, y)
        nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
        nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
    self.weights = [w-(eta/len(mini_batch))*nw
                    for w, nw in zip(self.weights, nabla_w)]
    self.biases = [b-(eta/len(mini_batch))*nb
                    for b, nb in zip(self.biases, nabla_b)]
   #这行代码在梯度下降最重要,backpropagation算法下次笔记详细说明
    delta_nabla_b, delta_nabla_w = self.backprop(x, y)

完整的神经网络实现代码

代码原github地址

import random

# Third-party libraries
import numpy as np

class Network(object):

    def __init__(self, sizes):
        """The list ``sizes`` contains the number of neurons in the
        respective layers of the network.  For example, if the list
        was [2, 3, 1] then it would be a three-layer network, with the
        first layer containing 2 neurons, the second layer 3 neurons,
        and the third layer 1 neuron.  The biases and weights for the
        network are initialized randomly, using a Gaussian
        distribution with mean 0, and variance 1.  Note that the first
        layer is assumed to be an input layer, and by convention we
        won't set any biases for those neurons, since biases are only
        ever used in computing the outputs from later layers."""
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        self.weights = [np.random.randn(y, x)
                        for x, y in zip(sizes[:-1], sizes[1:])]

    def feedforward(self, a):
        """Return the output of the network if ``a`` is input."""
        for b, w in zip(self.biases, self.weights):
            a = sigmoid(np.dot(w, a)+b)
        return a

    def SGD(self, training_data, epochs, mini_batch_size, eta,
            test_data=None):
        """Train the neural network using mini-batch stochastic
        gradient descent.  The ``training_data`` is a list of tuples
        ``(x, y)`` representing the training inputs and the desired
        outputs.  The other non-optional parameters are
        self-explanatory.  If ``test_data`` is provided then the
        network will be evaluated against the test data after each
        epoch, and partial progress printed out.  This is useful for
        tracking progress, but slows things down substantially."""
        if test_data: n_test = len(test_data)
        n = len(training_data)
        for j in xrange(epochs):
            random.shuffle(training_data)
            mini_batches = [
                training_data[k:k+mini_batch_size]
                for k in xrange(0, n, mini_batch_size)]
            for mini_batch in mini_batches:
                self.update_mini_batch(mini_batch, eta)
            if test_data:
                print "Epoch {0}: {1} / {2}".format(
                    j, self.evaluate(test_data), n_test)
            else:
                print "Epoch {0} complete".format(j)

    def update_mini_batch(self, mini_batch, eta):
        """Update the network's weights and biases by applying
        gradient descent using backpropagation to a single mini batch.
        The ``mini_batch`` is a list of tuples ``(x, y)``, and ``eta``
        is the learning rate."""
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        for x, y in mini_batch:
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
            nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
        self.weights = [w-(eta/len(mini_batch))*nw
                        for w, nw in zip(self.weights, nabla_w)]
        self.biases = [b-(eta/len(mini_batch))*nb
                       for b, nb in zip(self.biases, nabla_b)]

    def backprop(self, x, y):
        """Return a tuple ``(nabla_b, nabla_w)`` representing the
        gradient for the cost function C_x.  ``nabla_b`` and
        ``nabla_w`` are layer-by-layer lists of numpy arrays, similar
        to ``self.biases`` and ``self.weights``."""
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # feedforward
        activation = x
        activations = [x] # list to store all the activations, layer by layer
        zs = [] # list to store all the z vectors, layer by layer
        for b, w in zip(self.biases, self.weights):
            z = np.dot(w, activation)+b
            zs.append(z)
            activation = sigmoid(z)
            activations.append(activation)
        # backward pass
        delta = self.cost_derivative(activations[-1], y) * \
            sigmoid_prime(zs[-1])
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())
        # Note that the variable l in the loop below is used a little
        # differently to the notation in Chapter 2 of the book.  Here,
        # l = 1 means the last layer of neurons, l = 2 is the
        # second-last layer, and so on.  It's a renumbering of the
        # scheme in the book, used here to take advantage of the fact
        # that Python can use negative indices in lists.
        for l in xrange(2, self.num_layers):
            z = zs[-l]
            sp = sigmoid_prime(z)
            delta = np.dot(self.weights[-l+1].transpose(), delta) * sp
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l-1].transpose())
        return (nabla_b, nabla_w)

    def evaluate(self, test_data):
        """Return the number of test inputs for which the neural
        network outputs the correct result. Note that the neural
        network's output is assumed to be the index of whichever
        neuron in the final layer has the highest activation."""
        test_results = [(np.argmax(self.feedforward(x)), y)
                        for (x, y) in test_data]
        return sum(int(x == y) for (x, y) in test_results)

    def cost_derivative(self, output_activations, y):
        """Return the vector of partial derivatives \partial C_x /
        \partial a for the output activations."""
        return (output_activations-y)

#### Miscellaneous functions
def sigmoid(z):
    """The sigmoid function."""
    return 1.0/(1.0+np.exp(-z))

def sigmoid_prime(z):
    """Derivative of the sigmoid function."""
    return sigmoid(z)*(1-sigmoid(z))

实现一个手写数字识别程序

手写识别的参考代码

1.加载mnist数据集
2.查看下返回的训练集、测试集和验证集的数据类型和长度(数据结构搞清楚)
3.创建神经网络
4.进行梯度下降,获得优化后的神经网络模型参数
5.对算法进行准确性评估

#coding=utf-8

import mnist_loader
from network import Network

trainDataset,validationDataset,testDataset = mnist_loader.load_data_wrapper()
# 训练集是一个50000长度的list,每个元素是一个元祖(x,y),x表示输入特征(768),y表示所属数字label
# print(len(trainDataset))
# print(len(trainDataset[0]))
# # x的结构
# print(trainDataset[0][0].shape)
# # y的结构
# print(trainDataset[0][1].shape)

# list里面是每层神经网络的神经数量
network = Network([784,50,10])
# 进行梯度下降,并测试
network.SGD(trainDataset,30,10,3.0,test_data=testDataset)
2019-03-27 20:06:15 qq_41997920 阅读数 319
  • 笔记式Python基础入门

    您观看课程学习后 免费入群领取【超全Python资料包+17本学习电子书】 课程简介:以笔记为导向作为讲解内容是本人一贯的授课亮点,一条笔记包含一个知识点,本课程450多条笔记涵盖了python所有入门知识点,非常适合作为入门课程。

    2076 人正在学习 去看看 翁老师

1.概念

1.1 什么是迁移学习?

深度学习算法应用过程中,数据规模大,训练时间长是我们遇到到一大问题,那么在搭建好深度神经网络模型后,我们还需要大量的算力和时间训练和参数的优化,使得性价比非常低。我们就考虑同类问题的模型迁移,这样提高模型的性价比。考虑刀片没有免费午餐原理,我们尽可能的提高模型的泛化能力以及鲁棒性。需要注意的是,我们在使用迁移学习的过程中有事会导致迁移模型的负迁移,我们可以理解为模型的泛化能力的恶化。当利用同一模型处理两个相关性很小的问题就很容易出现这种情况。

2.数据读取

我们将使用kaggle dogs vs.cats数据集进行模型的迁移,首先我们需要对数据集进行处理。

import torch
import torchvision
from torchvision import datasets,models,transforms
import os
import matplotlib.pyplot as plt
from torch.autograd import Variable
import time
#torchvision包主要实现数据的处理,导入和预览,以下数据的导入我们将使用这个包

2.1数据集处理

关于kaggle dogs vs.cats数据集,官网提供的train和test,其中train data包含25000张猫狗的照片,且数量相同。但test data中的猫狗是无序混乱的,且没有label。为了增加模型的泛化能力,我们从训练集中选出一部分做验证集。关于train data ,test data ,valid data的区别下面详细说明一下。

1. 训练数据(Training Set)

     用于调整网络的权重(weights)和偏差(biases)。 

2. 验证数据(Validation Set)

    验证数据用于最小化过拟合(overfitting)。训练完成之后,使用测试数据验证其准确度是否满足要求,即验证其推广/泛化能力。

    这数据不调整权重和偏差。在基于训练数据调整权重之后,如果基于训练数据的准确度增加了,而基于验证数据的准确度没有增加或反而下降了,则表明过拟合(overfitting)了,需要立即停止训练。

3. 测试数据(Testing Set)

    在训练完成之后,使用测试数据确认网络真正的预测和分类能力。

4. Ground Truth

    在有监督学习中,数据是有标注的,以(x, t)的形式出现,其中x是输入数据,t是标注。正确的t标注是Ground Truth, 错误的标记则不是。(也有人将所有标注数据都叫做Ground Truth)

 

所以为了使得模型具有很高的准确率和低损值,我们将验证集看作模拟的训练集,将测试集看作最终的测试,从而提高泛化能力。

2.2数据集预览

获取全部的数据集之后,我们就可以对这些数据进行简单分类了。新建一个名为DogsVSCats的文件夹,在该文件夹下面新建一个名为train和一个名为valid的子文件夹,在子文件夹下面再分别新建一个名为cat的文件夹和一个名为dog的文件夹,最后将数据集中对应部分的数据放到对应名字的文件夹中,之后就可以进行数据的载入了。

data_dir = "DogsVSCats"
data_transform = {x:transforms.Compose([transforms.Scale([224,224]),
                                        transforms.ToTensor(),
                                        transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5,0.5,0.5])])
                  for x in ["train", "valid"]}

image_datasets = {x:datasets.ImageFolder(root = os.path.join(data_dir,x),
                                         transform = data_transform[x])
                  for x in ["train", "valid"]}

dataloader = {x:torch.utils.data.DataLoader(dataset= image_datasets[x],
                                            batch_size = 16,
                                            shuffle = True)
                  for x in ["train", "valid"]}

判断是否支持GPU

Use_gpu = torch.cuda.is_available()

3.模型的迁移

以下代码中我们将进行下载的模型是VGG16,并通过设置prepaer=True中的值为Ture,来实现下载的模型附带了已经优化好的

模型参数。

model = models.vgg16(pretrained=True)

第二步需要对迁移的模型进行调整。在迁移学习中全连接层是我们经常调整的部分。思想是冻结卷积神经网络中全连接层之前的所有网络,让这些被冻结的网络层次中的参数不进行梯度更新,能够被优化的参数仅仅是没有被冻结的全连接层的全部参数。

代码调整如下:

or parma in model.parameters():
    parma.requires_grad = False
    model.classifier = torch.nn.Sequential(torch.nn.Linear(25088, 4096),
                                           torch.nn.ReLU(),
                                           torch.nn.Dropout(p=0.5),
                                           torch.nn.Linear(4096, 4096),
                                           torch.nn.ReLU(),
                                           torch.nn.Dropout(p=0.5),
                                           torch.nn.Linear(4096, 2))
if Use_gpu:
    model = model.cuda()

cost = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.classifier.parameters())
loss_f = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.classifier.parameters(), lr = 0.00001)
epoch_n = 5

首先,对原模型中的参数进行遍历操作,将参数中的parma.requires_grad全部设置为False,这样对应的参数将不计算梯度,
当然也不会进行梯度更新了,这就是之前说到的冻结操作;然后,定义新的全连接层结构并重新赋值给model.classifier。在完成了新的全连接层定义后,全连接层中的parma.requires_grad参数会被默认重置为True,所以不需要再次遍历参数来进行解冻操作。损失函数的loss值依然使用交叉熵进行计算,但是在优化函数中负责优化的参数变成了全连接层中的所有参数,即对  model.classifier.parameters这部分参数进行优化。

time_open = time.time()
for epoch in range(epoch_n):
    print("Epoch {}/{}".format(epoch, epoch_n - 1))
    print("-"*10)
    for phase in ["train", "valid"]:
        if phase == "train":
            print("Training...")
            model.train(True)
        else:
            print("Validing...")
            model.train(False)
            
    running_loss = 0.0
    running_corrects = 0
    for batch, data in enumerate(dataloader[phase], 1):

        X, y = data
        if Use_gpu:
            X, y = Variable(X.cuda()), Variable(y.cuda())
        else:
            X, y = Variable(X), Variable(y)
            
        y_pred = model(X)
        _, pred = torch.max(y_pred.data, 1)
        optimizer.zero_grad()
        loss = loss_f(y_pred, y)
        
        if phase == "train":
            loss.backward()
            optimizer.step()
            running_loss += loss.data[0]
            running_corrects += torch.sum(pred == y.data)
            
            if batch%500 == 0 and phase =="train":
                print("Batch {}, Train Loss:{:.4f}, Train ACC:{:.4f}".format(batch, running_loss/batch, 100*running_corrects(16*batch)))

    epoch_loss = running_loss*16/len(image_datasets[phase])
    epoch_acc = 100*running_corrects/len(image_datasets[phase])
    print("{} Loss:{:.4f} Acc:{:.4f}%".format(phase, epoch_loss,epoch_acc))
            
time_end = time.time() - time_open
print(time_end)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

没有更多推荐了,返回首页