机器学习笔记01:线性回归;Softmax与分类模型、多层感知机

线性回归

1.1 线性回归的损失函数

机器学习笔记01:线性回归;Softmax与分类模型、多层感知机

通常,我们用训练数据集中所有样本误差的平均来衡量模型预测的质量,即

机器学习笔记01:线性回归;Softmax与分类模型、多层感知机

在模型训练中,我们希望找出⼀组模型参数,来使训练样本平均损失最小。


机器学习笔记01:线性回归;Softmax与分类模型、多层感知机

1.2 LR和线性回归的区别

线性回归用来做预测,LR用来做分类。线性回归是来拟合函数,LR是来预测函数。线性回归用最小二乘法来计算参数,LR用最大似然估计来计算参数。线性回归更容易受到异常值的影响,而LR对异常值有较好的稳定性。


1.3 SGD,Monentum,Adagard,Adam原理

sgd:sgd为梯度随机下降,每一次迭代计算数据集的mini-batch梯度,然后对参数进行更新。Momnentum参考了物理学中的动量的概念,前几次的梯度也会参与到当前的计算中来,但是前几轮的梯度叠加到当前的计算中还是会有一定的衰减。Adagard在训练过程中可以改变学习的速率,设置一个全局的学习率,而实际的学习率与以往的参数模的开方成反比。Adam利用梯度的一阶矩估计和二阶矩估计来动态调整每个参数的学习率,在经过偏置调整以后,每一次迭代的学习率都有一个确定的范围,使得参数较为平稳。
参考文献:https://blog.csdn.net/u010089444/article/details/76725843

线性回归模型使用pytorch的简洁实现

<code>import torch
from torch import nn
import numpy as np
torch.manual_seed(1)

print(torch.__version__)
torch.set_default_tensor_type('torch.FloatTensor')

生成数据集
num_inputs = 2
num_examples = 1000

true_w = [2, -3.4]
true_b = 4.2


features = torch.tensor(np.random.normal(0, 1, (num_examples, num_inputs)), dtype=torch.float)
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float)

读取数据集
import torch.utils.data as Data

batch_size = 10

# combine featues and labels of dataset
dataset = Data.TensorDataset(features, labels)

# put dataset into DataLoader
data_iter = Data.DataLoader(
dataset=dataset, # torch TensorDataset format
batch_size=batch_size, # mini batch size
shuffle=True, # whether shuffle the data or not
num_workers=2, # read data in multithreading
)

定义模型
class LinearNet(nn.Module):
def __init__(self, n_feature):
super(LinearNet, self).__init__() # call father function to init
self.linear = nn.Linear(n_feature, 1) # function prototype: `torch.nn.Linear(in_features, out_features, bias=True)`

def forward(self, x):
y = self.linear(x)
return y

net = LinearNet(num_inputs)
print(net)

# ways to init a multilayer network
# method one
net = nn.Sequential(
nn.Linear(num_inputs, 1)
# other layers can be added here
)

# method two
net = nn.Sequential()
net.add_module('linear', nn.Linear(num_inputs, 1))
# net.add_module ......

# method three
from collections import OrderedDict
net = nn.Sequential(OrderedDict([
('linear', nn.Linear(num_inputs, 1))

# ......
]))

print(net)
print(net[0])

模型初始化
from torch.nn import init

init.normal_(net[0].weight, mean=0.0, std=0.01)
init.constant_(net[0].bias, val=0.0) # or you can use `net[0].bias.data.fill_(0)` to modify it directly

for param in net.parameters():
print(param)

定义损失函数
loss = nn.MSELoss() # nn built-in squared loss function
# function prototype: `torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')`

定义优化函数
import torch.optim as optim

optimizer = optim.SGD(net.parameters(), lr=0.03) # built-in random gradient descent function
print(optimizer) # function prototype: `torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)`

训练
num_epochs = 3
for epoch in range(1, num_epochs + 1):
for X, y in data_iter:
output = net(X)
l = loss(output, y.view(-1, 1))
optimizer.zero_grad() # reset gradient, equal to net.zero_grad()
l.backward()
optimizer.step()
print('epoch %d, loss: %f' % (epoch, l.item()))

# result comparision
dense = net[0]
print(true_w, dense.weight.data)
print(true_b, dense.bias.data)/<code>


Softmax与分类模型

2.1 什么是交叉熵

参考资料:https://www.cnblogs.com/kyrieng/p/8694705.html


2.2 神经网络为什么要用交叉熵

通过神经网络解决多分类问题时,最常用的一种方式就是在最后一层设置n个输出节点,无论在浅层神经网络还是在CNN中都是如此,比如,在AlexNet中最后的输出层有1000个节点,而即便是ResNet取消了全连接层,也会在最后有一个1000个节点的输出层。一般情况下,最后一个输出层的节点个数与分类任务的目标数相等。假设最后的节点数为N,那么对于每一个样例,神经网络可以得到一个N维的数组作为输出结果,数组中每一个维度会对应一个类别。在最理想的情况下,如果一个样本属于k,那么这个类别所对应的的输出节点的输出值应该为1,而其他节点的输出都为0,即[0,0,1,0,….0,0],这个数组也就是样本的Label,是神经网络最期望的输出结果,交叉熵就是用来判定实际的输出与期望的输出的接近程度。


2.3 softmax的原理

参考资料:https://www.nowcoder.com/ta/review-ml/review?tpId=96&tqId=32711&query=Softmax&asc=true&order=&page=3

softmax的简洁实现

<code># 加载各种包或者模块
import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

print(torch.__version__)

初始化参数和获取数据
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, root='/home/kesci/input/FashionMNIST2065')

定义网络模型
num_inputs = 784
num_outputs = 10

class LinearNet(nn.Module):
def __init__(self, num_inputs, num_outputs):
super(LinearNet, self).__init__()
self.linear = nn.Linear(num_inputs, num_outputs)
def forward(self, x): # x 的形状: (batch, 1, 28, 28)
y = self.linear(x.view(x.shape[0], -1))
return y

# net = LinearNet(num_inputs, num_outputs)

class FlattenLayer(nn.Module):
def __init__(self):
super(FlattenLayer, self).__init__()
def forward(self, x): # x 的形状: (batch, *, *, ...)
return x.view(x.shape[0], -1)

from collections import OrderedDict
net = nn.Sequential(
# FlattenLayer(),
# LinearNet(num_inputs, num_outputs)
OrderedDict([
('flatten', FlattenLayer()),
('linear', nn.Linear(num_inputs, num_outputs))]) # 或者写成我们自己定义的 LinearNet(num_inputs, num_outputs) 也可以
)

初始化模型参数
init.normal_(net.linear.weight, mean=0, std=0.01)
init.constant_(net.linear.bias, val=0)

定义损失函数
loss = nn.CrossEntropyLoss() # 下面是他的函数原型
# class torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')

定义优化函数
optimizer = torch.optim.SGD(net.parameters(), lr=0.1) # 下面是函数原型
# class torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)

训练
num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)/<code>


多层感知机

3.1 激活函数的作用

激活函数是用来加入非线性因素的,提高神经网络对模型的表达能力,解决线性模型所不能解决的问题。
3.2 神经网络的激活函数有哪几种,函数图像,特点,互相比较,优缺点以及改进方法

参考资料:https://www.nowcoder.com/questionTerminal/aebd2ff95deb4661856e57c129bc074d
sigmod、tanh、relu

sigmod函数:

函数图像及梯度函数图像:

机器学习笔记01:线性回归;Softmax与分类模型、多层感知机

优点:它是便于求导的平滑函数,其导数为缺点:

  • 梯度消失
  • 幂运算计算量大
  • Sigmoid函数的输出不不是Zero-centered的


tanh函数:

函数图像及梯度函数图像:

机器学习笔记01:线性回归;Softmax与分类模型、多层感知机

如上图所示,计算可以知道:它其实是一个简单放大的sigmoid神经元,和sigmoid神经元⼀样,也具有软饱和性。但是和sigmoid神经元不同的是,它解决了zero-centered的输出问题,因此,在实际操作中,tanh非线性函数比sigmoid非线性函数更受欢迎。然而,gradient vanishing的问题和幂运算的问题仍然存在。因为tanh的输出均值比sigmoid更接近0,SGD会更更接近natural gradient(一种二次优化技术),从而降低所需的迭代次数。

relu函数:

函数图像及梯度函数图像:

机器学习笔记01:线性回归;Softmax与分类模型、多层感知机

优点:

  • 解决了gradient vanishing问题:ReLU在x<0时硬饱和。由于时导数为1,所以,ReLU能够在时保持梯度不衰减,从而缓解梯度消失问题。
  • 计算速度非常快。对比sigmoid和tanh神经元含有指数运算等耗费计算资源的操作,ReLU可以简单地通过对⼀个矩阵进行阈值计算得到。ReLU程序实现就是一个if-else语句句,而sigmoid函数要进行浮点四则运算
  • 收敛速度非常快。相较于sigmoid和tanh函数,ReLU对于随机梯度下降的收敛有巨大的加速作用。
  • ReLU另外一个性质是提供神经网络的稀疏表达能力,relu函数在负半区的导数为0 ,所以一旦神经元激活值进入负半区,那么梯度就会为0,也就是说这个神经元不会经历训练,即所谓的稀疏性。

缺点:

  • Dead ReLU Problem。随着训练的推进,部分输入会落入硬饱和区,某些神经元可能永远不会被激活,这个ReLU单元在训练中将不可逆转的死亡,导致相应的参数永远不能被更新,使得数据多样化丢失。
  • 偏移现象。即输出均值恒大于零。偏移现象和Dead ReLU Problem会共同影响网络的收敛性。


3.3 解释一下硬饱和和软饱和

硬饱和:如果|x|>c时,有f^'(x)=0,那么就可以称为硬饱和,比如有relu,为左硬饱和软饱和:如果|x|>c时,有f^'(x)趋近于0,那么就可以称为软饱和,比如有sigmoid和relu,为软饱和。

多层感知机pytorch实现


<code>import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

print(torch.__version__)

初始化模型和各个参数
num_inputs, num_outputs, num_hiddens = 784, 10, 256

net = nn.Sequential(
d2l.FlattenLayer(),
nn.Linear(num_inputs, num_hiddens),
nn.ReLU(),
nn.Linear(num_hiddens, num_outputs),
)

for params in net.parameters():
init.normal_(params, mean=0, std=0.01)

训练
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')
loss = torch.nn.CrossEntropyLoss()

optimizer = torch.optim.SGD(net.parameters(), lr=0.5)

num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)/<code>
<code>机器import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

print(torch.__version__)

初始化模型和各个参数
num_inputs, num_outputs, num_hiddens = 784, 10, 256

net = nn.Sequential(
d2l.FlattenLayer(),
nn.Linear(num_inputs, num_hiddens),
nn.ReLU(),
nn.Linear(num_hiddens, num_outputs),
)

for params in net.parameters():
init.normal_(params, mean=0, std=0.01)

训练
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')
loss = torch.nn.CrossEntropyLoss()

optimizer = torch.optim.SGD(net.parameters(), lr=0.5)

num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)/<code>


分享到:


相關文章: