pytorch 神经网络基本笔记

我从今天开始学pytorch,照着训练分类器官方用例来写。1 数学知识1.1 交叉熵损失1.1.1 log2(x)从下图可以看到x在0~1之间,x越小,那么y值越大import numpy as npimport mathimport matplotlib.pyplot as plt# axisartist包就用来设置坐标轴的类型import mpl_toolkits.axis...
摘要由CSDN通过智能技术生成

我从今天开始学pytorch,照着训练分类器官方用例来写。
1 数学知识
1.1 交叉熵损失
1.1.1 log2(x)
从下图可以看到x在0~1之间,x越小,那么y值越大
1

import numpy as np
import math
import matplotlib.pyplot as plt
# axisartist包就用来设置坐标轴的类型
import mpl_toolkits.axisartist as axisartist
# 数据
x = np.arange(0.05,5,0.05)
y = [-math.log(a,2) for a in x]
# 坐标系
fig = plt.figure(figsize=(8,8))
ax = axisartist.Subplot(fig,1,1,1)
fig.add_axes(ax)
# 设置绘图区原有坐标轴隐藏,否则自动自定义的坐标轴,就会原有的坐标轴有数字的重合,看起啦比较乱
ax.axis[:].set_visible(False)
# 添加新的坐标轴x
ax.axis["x"] = ax.new_floating_axis(0,0)
ax.axis["x"].set_axisline_style("-|>", size = 1.0)
ax.axis["x"].set_axis_direction("top")
# 添加新的坐标轴y
ax.axis["y"] = ax.new_floating_axis(1,0)
ax.axis["y"].set_axisline_style("-|>", size = 1.0)
ax.axis["y"].set_axis_direction("right")
# 画图
plt.plot(x,y,'-g',label='log2(x)')
plt.legend(loc='lower right')
plt.xlim(0,6)
plt.ylim(-5, 5)
plt.show()

1.1.2 信息量
参考熵与信息增益中对信息量的描述:
信息量是用来衡量一个事件的不确定性的;一个事件发生的概率越大,不确定性越小,则它所携带的信息量就越小,给出的公式为I(x)=−log(p(x)),理解这句话参考上面图,就知道了。
1.1.3 信息量的期望
HA(x)=−[p(xA)log(p(xA))+(1−p(xA))log(1−p(xA))],其中p(xA)是某个事件发生的概率
1.1.3 熵
上面的信息量只是一个事件,而熵是衡量一个系统(所有事件)的信息量的期望
H(X)=Eplog1p(x)=−∑x∈Xp(x)logp(x),如果p(x)是连续型随机变量的p(df),则熵定义为H(X)=−∫x∈Xp(x)logp(x)dx。具体公式不再次描述
下图这个当只有两种概率的情况,例如中彩票的场景,展现出来的曲线。当p(x)=0.5时,不确定度最大,熵也越大
1

# np.linspace与arange类似,产生指定范围内的均匀间隔的数字
x = np.linspace(0,1,50)
# 防止数值溢出,这个值还是很有必要
epslion= 1e-10
y = -(x*np.log2(x+epslion)+(1-x)*np.log2(1-x+epslion))
# 画图
plt.plot(x,y,'-g',label='log2(x)')
plt.legend(loc='lower right')
plt.xlim(0,1)
plt.ylim(0,1)
plt.show()

1.4 相对熵
预测一个系统,需要考虑很多事件的概率,很难枚举全,也就是信息量不够,那就需要机器反复训练,发现一些增量信息,来缩小与真实值的差距,一文搞懂交叉熵在机器学习中的使用,透彻理解交叉熵背后的直觉

1.5 交叉熵
交叉熵是通过相对熵推导出来的,参考交叉熵——我们如何评估差异,系统中某种场景的实际信息熵是A,通过各种办法去尝试得出的预测信息熵B,B=A,那么预测的准确度就是100%了,不过有偏差,那么B-A的差值就是交叉熵,从这个角度看,做工程化就不一定非要理解交叉熵公式的推导了。这样也就不难理解为什么用交叉熵可以作为机器学习的loss函数了。在torch中定义比较简单

import torch.nn as nn
criterion = nn.CrossEntropyLoss()

1.6 各种函数
1.6.1 损失函数、代价函数
【机器学习】代价函数,损失函数,目标函数区别虽然描述损失函数是针对一个样本的误差,而整个训练集所有误差的平均,但实际用的时候损失函数就是代价函数,代价函数就是损失函数
1.6.2 风险函数、目标函数
损失函数越小越好吗,不一定。对历史数据最好的拟合,不代表对未知数据的预测就一定最准,需要防止过度学习历史。那么怎么防止过拟合呢?于是有引入了风险函数(risk function),风险函数是损失函数的期望,而损失函数是估计值与实际值之差平方的期望。风险函数用来控制经验风险,
怎么让风险最小化呢,又搞了一个函数J(f),也叫正则化,来度量模型的复杂度,也就是来控制结构风险,模型太复杂,那么结构风险也就越大,模型过于简单,那么结构风险也越小。最优化经验风险和结构风险,最终得到了下面这个函数,也就是目标函数。目标函数的最优解,也就是经验风险和结构风险的平衡点
1
1.6.3 正则化、惩罚系数
参考损失、风险函数与正则化,正则化是控制结构风险,让模型变的简单,但面对大量的参数,我们不知道惩罚那些参数的系数,就从第1个开始试了。他有L1、L2两种范式,公式太复杂,我暂时理解不了,等那天看明白了,再做笔记。
机器学习之正则化(Regularization)
过多的变量(特征),过少的训练数据,就会产生过拟合的问题,解决办法

  1. 人工筛选
    人工减少特征变量,是基于经验,属于专家判断。但经验并不总是正确的,还有墨菲定律存在,忽略了那些能够产生蝴蝶效应的变量。
  2. 正则化
    保留所有的特征变量,但是减少特征变量的数量级。也就减轻那些变量对总体代价函数的影响了

1.6.4 优化函数
正则化防止过拟合,如果更快地找到损失函数达到最佳呢,就涉及优化过程。这个优化过程使用的函数就是优化函数。损失函数和优化-损失函数(1),采取的方法就是下面提到的梯度下降。
1.6.5 学习率
深度学习: 学习率 (learning rate)这篇文章分享了一些学习率设置的经验,学习率(Learning rate)的理解以及如何调整学习率给出学习率的定义:决定着目标函数能否收敛到局部最小值以及何时收敛到最小值。
学习率设置过大,梯度可能在会在最小值附近来回震荡,跨过最优值而无法收敛。这也就知道优化函数与学习率的关系了。深度学习(五)学习率的调节给出了函数关系描述,就更容易明白了。
新权值 = 当前权值 – 学习率 × 梯度
1.6.6 激励函数、激活函数
机器学习中的这些名词都容易把人搞晕,只能抽丝拨茧,看看每个名词都是啥关系,常用激活函数(激励函数)理解与总结,也就是说激励函数就是激活函数。前面几个函数逻辑还是比较容易理解的。如果想回归,也就是将预测值与实际值达到最佳匹配,就需要让损失函数达到最佳,损失函数并不是最大或最小为好,需要找到最优解,就把损失函数作为基础,构建一个目标函数,最终通过正则化减少结构风险让模型简单化,通过风险函数来防优化学习经验,也就是不要瞎学。怎么又多了一个激活函数呢?他是用来解决什么的呢?
激活函数是神经网络中的概念,上层的输出做为下层的输入,这两个之间存在一个函数关系,这个函数关系就是激活函数或者激励函数。如果不用激活函数,那么上层的输出就是下层的输入,这个世界好像没有那么美好的线性关系。深度学习中常用的激励函数中的解释比较容易理解
这几年研究,主要采取Relu作为激励函数,他的速度快与sigmoid和tanh,这里介绍一下。
ReLU激活函数:简单之美中的解释,relu函数更符合生物特性,神经元工作的稀疏性,与relu函数曲线神似。
1.7 MSE(均方误差)函数
MSE均方误差是指参数估计值与参数真值之差平方的期望值;
MSE可以评价数据的变化程度,MSE的值越小,说明预测模型描述实验数据具有更好的精确度
MSE(均方误差)函数和RMSE函数,
均方误差(MSE)和均方根误差(RMSE)和平均绝对误差(MAE)
,从这两边可以看到一文搞懂交叉熵在机器学习中的使用,透彻理解交叉熵背后的直觉给出的公式乍一看,还以为是错误的。这里的问题是

  1. 为什么机器学习中的MSE计算还要除以2呢?看了这篇文章机器学习中的均方误差为什么还除以2,原来是因为:因为带了平方,后面要用梯度下降法,要求导,这样求导多出的乘2就和二分之一抵消了.
  2. MSE适合做线性回归,那是否适合逻辑回归呢?以及上面提出交叉熵作为loss函数,那么结论就容易推导:显然是不适合,具体参考一、线性回归和逻辑回归,线性回归可以预测连续值,但是不能解决分类问题。
  3. 那么什么是线性回归,什么时候逻辑回归呢?什么是回归呢?超级干货 :一文读懂回归分析 这篇文章介绍了回归的来源,我的理解就是预测,通过什么方法缩小预测值与真实值的差距。拟合与回归——区别与联系

1.8 基于MSE的线性回归
线性拟合就是线性回归,线性回归中最常用的就是MSE
参考通俗理解线性回归(一)通俗理解线性回归(二),再结合pytorch 模拟关系拟合——回归中的代码,可以看到拟合的过程,注意torch版本不同,将loss.data[0]调整为loss.item
这篇文章的算法,参考机器学习算法——线性回归算法介绍

plt.text(0.5, 0, 'Loss=%.4f' % loss.item(), fontdict={'size': 20, 'color': 'red'})  # 显示损失数值

1.8.1 nn.Linear
定义一个线性层nn.Linear(in_features,out_features),背后的逻辑是什么呢
写个例子看看linear是怎么计算

import torch
import torch.nn as nn
x = torch.rand(3,1)
print(x)
print(x.shape)
hidden = nn.Linear(1,3)
print(hidden.weight)
print(hidden.weight.shape)
print(hidden.bias)
print(hidden.bias.shape)
output = hidden(x)
print(output)
print(output.shape)

将打印的结果,通过nump将计算过程分析如下: y = x ∗ w T + b y=x*w^{T}+b y=xwT+b
x是我们自己随机产生的,那么这个w和b是怎么产生的呢?

import numpy as np
x = np.array([[0.2618],
        [0.6930],
        [0.0848]]);
w = np.array([[ 0.8264],
        [-0.2916],
        [ 0.3315]]);
b = np.array([-0.2906, -0.0507, -0.4637]);
y = [[-0.0743, -0.1270, -0.3770],
        [ 0.2821, -0.2528, -0.2340],
        [-0.2206, -0.0754, -0.4356]];
print(x.dot(np.transpose(w))+b)

进入源码看到,可以看到weight、bias由Parameter(torch.Tensor(out_features, in_features))产生,而执行torch.Tensor(3,1)又会随机得到一个张量,那么这个初始值产生的逻辑是什么呢?如何初始化weights和biaspytorch学习之权重初始化,看了这两篇文章,但不能告诉我torch自身这两个参数是怎么初始化的。从表现来看应该是随机的,初始值并不重要,因为这些参数会发生变化。

    def __init__(self, in_features, out_features, bias=True):
        super(Linear, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.weight = Parameter(torch.Tensor(out_features, in_features))
        if bias:
            self.bias = Parameter(torch.Tensor(out_features))
        else:
            self.register_parameter('bias', None)
        self.reset_parameters()

1.8.2 optimizer.zero_grad()
torch代码解析 为什么要使用optimizer.zero_grad(),将梯度初始值置为0,也就是将上次迭代计算的梯度值清0。
1.9 梯度下降
1.9.1 梯度下降
参考Python 实现简单的梯度下降法中python的实现,梯度下降算法的Python实现没必要自己写一遍,故
如何理解梯度下降法
查看他的原理,最清晰的讲解各种梯度下降法原理与Dropout,让目标函数快速收敛,三要素:步长、方向、出发点。
从算法的实现,可以出学习率α在每次跑是固定的,权重和导数是计算出来的,机器学习的梯度下降算法中寻找最合适学习率“阿尔法”的意义是什么?,找到合适的α需要一定的经验哦。
1.9.2 随机梯度下降
既然选择了交叉熵作为损失函数,那怎么样让损失函数快速收敛呢,就需要找加速度变化最快的方向,有就是找预测值与实际值朝那个方向找,用最快的时间找到最小的差距,参考如何理解随机梯度下降为什么随机梯度下降方法能够收敛?,既然有人证明可以收敛,那我只管工程化就可以了

import torch.optim as optim
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

从这个代码再比较交叉熵损失函数的定义,并看不到直接的关联。
2 神经网络
2.1 一个很简单的网络
解读参考pytorch系列 —5以 linear_regression为例讲解神经网络实现基本步骤以及解读nn.Linear函数

class Net(nn.Module):
    '''
    定义神经网路
    '''
    def __init__(self,n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        # 隐藏层线性输出
        self.hidden = nn.Linear(n_feature,n_hidden)
        # 输出曾线性输出
        self.predict = nn.Linear(n_hidden,n_output)

    def forward(self,x):
        '''
        正向传播输入值,神经网络分析得到输出值
        :param x:
        :return:
        '''
        # 隐藏层计算
        # 激活函数:relu
        x = F.relu(self.hidden(x))
        # 输出值
        x = self.pre
net = Net(n_feature=1, n_hidden=10, n_output=1)

2.2 正向传播和反向传播
反向传播——通俗易懂,这篇文章公式推到过程非常详细,我忍不住赞美以及手抄写了一遍。
正向传播很容易理解,反向传播涉及到偏导的计算。十年前的数学知识,只好捡起来。
2.2.1 偏导
导数和偏导数的区别? ,两者没什么区别,都是变化率,只是维度问题。
2.2.2 链式法则
高等数据微积分中定理: y = f [ v ( x ) ] , 其 中 y = f ( u ) , u = v ( x ) 如 果 这 两 个 函 数 都 可 导 , 则 符 合 函 数 的 导 数 据 为 y=f[v(x)],其中y=f(u),u=v(x)如果这两个函数都可导,则符合函数的导数据为 y=f[v(x)],y=f(u),u=v(x)
d y d x = d y d u ∗ d u d x \frac{dy}{dx}=\frac{dy}{du}*\frac{du}{dx} dxdy=dudydxdu
实战中总不能没一个都推导,故需要记忆一些导数公式。
2.2.3 反向传播过程推导
依据是反向传播——通俗易懂这篇文章计算过程,做一下解读。
输入层 → \rightarrow 隐含层,这一阶段的偏置是 b 1 b_1 b1
n e t h 1 = w 1 ∗ i 1 + w 2 ∗ i 2 + b 1 ∗ 1 net_{h1}=w_1*i_1+w2*i_2+b_1*1 neth1=w1i1+w2i2+b11 n e t h 2 = w 3 ∗ i 1 + w 4 ∗ i 2 + b 1 ∗ 1 net_{h2}=w_3*i_1+w_4*i_2+b_1*1 neth2=w3i1+w4

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warrah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值