梯度是一个反向,函数值变大的方向
在做梯度下降时,自变量和因变量是参数和loss函数,参数的值会沿着梯度的方向即loss值更小的方向更新。
梯度下降的初始化会决定最后可以下降到哪个local minimum
可以有助于跳过局部最小值:加入惯性
常用激活函数
torch.sigmoid(a) 将输入的值全部映射到[0,1]区间
torch.tanh(a)
torch,relu(a)
第一种: torch.autograd.grad
x=torch.ones(1)
w=torch.full([1],2)
#w=torch.tensor([1.],required_grad=True)
w.requires_grad_()#告诉系统这个w需要更新
mse=F.mse_loss(torch.ones(1),x*w)
torch.autograd.grad(mse,[w])
第二种:loss.backward
x=torch.ones(1)
w=torch.full([1],2)
#w=torch.tensor([1.],required_grad=True)
mse=F.mse_loss(torch.ones(1),x*w)
mse.backward()
w.grad()#返回w的梯度信息
将输出的结果映射到一个维度,使所有输出的总和为1,符合概率分布的特征。适用于分类的时候。
还会使数值较大的经过softmax后相较于原来的与其他值的比例来说变得更大,可以把数值代表的信息放大。
p=F.softmax(a,dim=0)
δ k k \delta_{k}^k δkk:表示对于最后经过k层layer输出的sigmoid后的输出值与实际值在后向传播中的值
输入通过linear regression的hidden layer后 经过sigmoid函数将output映射到[0,1]区间。设定一个阈值,把回归问题转为二分类问题。
在logistic regression中,不去最大化准确率
使用cross-entropy做梯度下降
将输出的output和label当作两个概率分布,计算它们两个的交叉熵
p和q相等时,它们完全overlap,即kl散度为0
当label值作为one-hot encoding 时,它的熵为0,因为事件的发生是确定的。
F.cross_entropy(logits,torch,tensor([3])) #cross-entropy自带了,softmax+log操作
ce=softmax+log+nll_loss
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
batch_size=200
learning_rate=0.01
epochs=10
'''加载数据集'''
train_loader = torch.utils.data.DataLoader(
datasets.MNIST('../data', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('../data', train=False, transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True)
'''初始化w,b'''
w1=torch.randn(200,784,requires_grad=True)#将输出的size放在前面
b1=torch.randn(200,requires_grad=True)#requires_grad:设置为true才可以做梯度下降
w2=torch.randn(200,200,requires_grad=True)
b2=torch.randn(200,requires_grad=True)
w3=torch.randn(10,200,requires_grad=True)
b3=torch.randn(10,requires_grad=True)
torch.nn.init.kaiming_normal_(w1)#将w初始化为一个可以让梯度下降进行得更顺利地值
torch.nn.init.kaiming_normal_(w2)
torch.nn.init.kaiming_normal_(w3)
'''设置nn的计算'''
def forward(x):
[email protected]()+b1
x=F.relu(x)
x = x @ w2.t() + b2
x = F.relu(x)
x = x @ w3.t() + b3
x = F.relu(x)
return x
'''建立优化器和损失函数'''
optimizer=optim.SGD([w1,b1,w2,b2,w3,b3],lr=learning_rate)
criteron=nn.CrossEntropyLoss()
'''开始训练'''
for epoch in range(epochs):
for batch_idx,(data,target) in enumerate(train_loader):
data=data.view(-1,784)
logits=forward(data)
loss=criteron(logits,target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch_idx%100==0:
if batch_idx % 100 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
test_loss = 0
correct = 0
for data, target in test_loader:
data = data.view(-1, 28 * 28)
logits = forward(data)
test_loss += criteron(logits, target).item()
pred = logits.data.max(1)[1]
correct += pred.eq(target.data).sum()
test_loss /= len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
nn.Linear(input_dim,output_dim)#建立一个全连接层
建立一个nn得类的时候必须继承自nn.Module
还需要在代码中使用net=MLP()建立一个网络
使用relu函数:
相比于sigmoid,做后向算法更新每一层layer的梯度时,relu函数得计算比sigmoid函数求导要简单很多很多
device=torch.device("cuda:0")
net=MLP().to(device)
criteron=nn.CrossEntropyLoss().to(device)
logits=torch.rand(4,10)
pred=F.softmax(logits,dim=1)
pred_label=pred.argmax(dim=1)#[9,5,9,4]
label=torch.tensor([9,3,2,4])
correct=torch.eq(pred_label,label)#[1,0,0,1]
correct.sum().float().item/4#0.5
测试思路