动手学深度学习第一次打卡

这篇博客记录了作者初次学习深度学习的体验,涵盖Task01的线性回归、softmax分类和多层感知机,以及Task02的文本预处理、语言模型和循环神经网络的基础知识。通过从零开始实现模型,介绍了线性回归的梯度下降优化,softmax用于分类的逻辑,多层感知机的隐藏层和激活函数,并探讨了文本预处理的方法,如分词、建立字典和序列转换。最后,作者展示了如何使用循环神经网络进行序列预测和语言建模,训练过程和结果分析展示了模型的性能和预测能力。
摘要由CSDN通过智能技术生成

今年才开始接触深度学习,基本上是小白的状态,希望能利用疫情放假的这些日子好好学习一下深度学习。第一次打卡包括Task01和Task02两部分,Task01的学习任务又分为线性回归、Softmax与分类模型与多层感知机三个内容。

Task01

1.线性回归

首先提出要解决的问题是探索房价(price)与房屋面积(area)和房龄(age)两个要素之间的关系。
线性回归假设输出与各个输入之间是线性关系:
在这里插入图片描述
即价格=面积×面积权重+房龄×房龄权重+偏差。

其中房屋被称为样本(sample),实际房价被称作标签(label),用来预测标签的area和age被称作feature。

利用损失函数L来衡量价格预测值与真实值之间的误差,这里选用的损失函数为平方函数。最终想要达到的目的是使损失函数不断减小,实现更优的预测效果。
**图片**
优化函数采用mini-batch梯度下降法,先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch),然后求小批量中数据样本的平均损失有关模型参数的导数(梯度),最后用此结果与预先设定的一个正数的乘积(学习率)作为模型参数在本次迭代的减小量。
在这里插入图片描述
采用mini-batch梯度下降法的好处:mini-batch梯度下降法在普通梯度下降法的基础上进行改进,在一些情况下,输入样本数量较多,对整个训练集执行梯度下降法花费时间过长,采用mini-batch梯度下降法将训练集分割成多个小的子训练集,使一部分样本先执行梯度下降。

优化函数的两个步骤
(i)初始化模型参数,一般来说使用随机初始化;
(ii)我们在数据上迭代多次,通过在负梯度方向移动参数来更新每个参数。

此外使用矢量计算方法来进行矢量运算,与使用for循环的方法相比大大提高了计算效率。

从0实现线性模型

首先引入相关包和组件

#import packages and modules
%matplotlib inline
import torch
from IPython import display
from matplotlib import pyplot as plt
import numpy as np
import random

利用线性模型生成1000个数据集

# 输入特征数为2,area和age 
num_inputs = 2
# 输入样本数量为1000
num_examples = 1000

# 设定两个输入特征的权重w和偏差b
true_w = [2, -3.4]
true_b = 4.2

features = torch.randn(num_examples, num_inputs,dtype=torch.float32)
#按照房价与面积和房龄的公式计算标签
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.float32)

其中:
①torch.randn(sizes, out=None)→ Tensor
返回一个张量,包含了从标准正态分布(均值为0,方差为1,即高斯白噪声)中抽取的一组随机数。张量的形状由参数sizes定义。在这里函数的作用是返回float32类型的1000*2的随机矢量,作为age和area,存入feature中。
②torch.tensor(data, dtype=None, device=None, requires_grad=False)
torch.tensor()可以从data中的数据部分做拷贝(而不是直接引用),根据原始数据类型生成相应的torch.LongTensor,torch.FloatTensor,torch.DoubleTensor。
③numpy.random.normal(loc=0.0, scale=1.0, size=None)
此函数为高斯分布的概率密度函数,loc为概率分布的均值,对应着整个分布的中心center;scale为概率分布的标准差;size为输出的shape,默认为None。由于实际不可能完全符合线性关系,因此在上述计算labels的基础上再加上一个随机生成的高斯分布的偏差。

使用图像来展示生成的数据

plt.scatter(features[:, 1].numpy(), labels.numpy(), 1);

读取数据集

def data_iter(batch_size, features, labels):
    num_examples = len(features)#得到features的行数为1000
    indices = list(range(num_examples))
    random.shuffle(indices)  # 打乱列表
    for i in range(0, num_examples, batch_size):
        j = torch.LongTensor(indices[i: min(i + batch_size, num_examples)]) # the last time may be not enough for a whole batch
        yield  features.index_select(0, j), labels.index_select(0, j

①for i in range(0, num_examples, batch_size)循环的含义是i从0到num_examples循环,步长为batch_size,即把数据集num_examples个样本分成了num_examples/batch_size个,每个mini-batch中包含batch_size个样本。
②.index_select(0, j)的含义是按行索引,索引序号为j

定义权重w及偏差b

w = torch.tensor(np.random.normal(0, 0.01, (num_inputs, 1)), dtype=torch.float32)
b = torch.zeros(1, dtype=torch.float32)

w.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True)

Out:tensor([0.], requires_grad=True)

线性回归公式

def linreg(X, w, b):
    return torch.mm(X, w) + b

定义损失函数

def squared_loss(y_hat, y): 
    return (y_hat - y.view(y_hat.size())) ** 2 / 2

定义优化函数

def sgd(params, lr, batch_size): 
    for param in params:
        param.data -= lr * param.grad / batch_size # ues .data to operate param without gradient track

进行模型训练

# super parameters init
lr = 0.03
num_epochs = 5

net = linreg
loss = squared_loss

# training
for epoch in range(num_epochs):  # training repeats num_epochs times
    # in each epoch, all the samples in dataset will be used once
    
    # X is the feature and y is the label of a batch sample
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y).sum()  
        # calculate the gradient of batch sample loss 
        l.backward()  
        # using small batch random gradient descent to iter model parameters
        sgd([w, b], lr, batch_size)  
        # reset parameter gradient
        w.grad.data.zero_()
        b.grad.data.zero_()
    train_l = loss(net(features, w, b), labels)
    print('epoch %d, loss %f' % (epoch + 1, train_l.mean().item()))

out:
epoch 1, loss 0.045923
epoch 2, loss 0.000187
epoch 3, loss 0.000055
epoch 4, loss 0.000055
epoch 5, loss 0.000055

定义学习率为0.03,迭代次数为5,进行5次迭代,在每次迭代中计算损失函数,进行反向传播,将参数代入优化函数中,得到训练后的损失函数。

分别输出训练前后的权重及偏差

w, true_w, b, true_b

out:
(tensor([[ 0.1838], [-0.4229]], requires_grad=True), [2, -3.4],
tensor([4.3392], requires_grad=True), 4.2)

线性回归模型使用pytorch的简洁实现
引用相关包和组件

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)

读取数据集,将特征和标签组合形成数据集,利用DataLoader取数据集。

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,               # 打乱数据
    num_workers=2,              # 双线程读取数据
)

接下来是利用pytorch模块实现模型,首先定义线性网络的,然后调用类实现网络的实例化
之前并没有接触过这样的概念,因此我查询了一下python中类和实例化的概念:
python类和实例化
简而言之,可以把类看作是一个模版,类下有不同的方法,在创建实例时候将必要的属性填写进去,在方法内部,self表示创建实例本身,因此类方法的参数传递中self不需要传参。

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)

生成一个单层线性网络:
LinearNet( (linear): Linear(in_features=2, out_features=1, bias=True) )

上面只初始化了一个线性层,实际上还可以生成多层网络,这里用到了Sequential序贯模型,给出了三种方法。
深入学习Keras中Sequential模型及方法

# ways to init a multilayer network
# method one
net = nn.Sequential(nn.Linear(num_inputs, 1))
# 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])

可以看到生成的网络如下:Sequential( (linear): Linear(in_features=2, out_features=1, bias=True))
Linear(in_features=2, out_features=1, bias=True)
即全部网络只有一层线性层,网络的第一层,也就是唯一的一层如Linear所示。

初始化模型参数w和b,采用init模块来初始化参数,选择不同的初始化模式,输入需要初始化的变量以及特征。

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

直接调用nn中的均方误差损失函数

loss = nn.MSELoss() 

调用torch中的随机梯度下降优化函数

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)

进行训练,设定迭代次数为3,迭代过程同上,只不过利用pytorch实现中间函数

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()))

out:
epoch 1, loss: 0.000422
epoch 2, loss: 0.000075
epoch 3, loss: 0.000176
比较一下训练后和真实的权重w以及偏差b

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

out:
[2, -3.4] tensor([[ 1.9996, -3.4005]])
4.2 tensor([4.1993])

2.softmax分类模型

softmax也是一个单层神经网络,其输出层是一个全连接层,即每个输出依赖于所有的输入。
在这里插入图片描述
用softmax实现图像分类可以进行如下理解:输入x为图片像素,输出o为分类结果。每个输出与输入之间都存在一个权重w,值最大的输出即可看作预测出的图像类别。有如下关系:
在这里插入图片描述
softmax运算符通过计算将输出值变换成值为正且和为1的概率分布,计算公式如下:
在这里插入图片描述
softmax回归的矢量计算表达式为:
在这里插入图片描述
损失函数采用交叉熵损失函数
在这里插入图片描述
使用准确率(accuracy)来评价模型的表现,其中准确率=正确预测数量/总预测数量。

下面是获取Fashion-MNIST训练集和读取数据
的一些代码:

导入需要的包。

# import needed package
%matplotlib inline
from IPython import display
import matplotlib.pyplot as plt

import torch
import torchvision
import torchvision.transforms as transforms
import time

import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

print(torch.__version__)
print(torchvision.__version__)

获得数据集mnist_train和mnist_test。

mnist_train = torchvision.datasets.FashionMNIST(root='/home/kesci/input/FashionMNIST2065', train=True, download=True,
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值