3.1. 线性回归 — 动手学深度学习 2.0.0-beta1 documentation

目录

3.1. 线性回归 — 动手学深度学习 2.0.0-beta1 documentation

3.1 线性回归

3.1.1 线性回归的基本元素

3.1.1.2 损失函数

3.1.1.3 解析解

3.1.1.4 随机梯度下降

3.1.2 矢量化加速

3.2 线性回归从零开始实现

3.3 线性回归的简洁实现

3.4 softmax回归

分类和回归

独热编码(one-hot encoding):

置信度:

损失函数

L2 loss(均方损失)

L1 loss

Huber 's Robust Loss

softmax:

交叉熵:

3.5 图像分类数据集

3.6 softmax回归的从零开始实现


3.1 线性回归

3.1.1 线性回归的基本元素

训练数据集(training data set)或训练集(training set):

想要开发一个具有一定功能的模型,必须要有大量的相关事例作为数据集,这些事例就是训练集。有了这一些事例,就可以根据自变量和因变量之间的关系来作为模型预测的依据。

样本(sample):

每组数据就是样本,也可以称为数据点(data point)或数据样本(data instance)

标签(label)或目标(target):试图预测的目标。

特征(feature)或协变量(covariate):预测所依据的自变量。

3.1.1.1 线性回归模型

b称为偏置(bias)、偏移量(offset)或截距(intercept) 不可缺少的

w称为权重(weight)

数据集的意义是帮我们找到相对合适的b和w

即使确信特征与标签的潜在关系是线性的, 我们也会加入一个噪声项来考虑观测误差带来的影响。

3.1.1.2 损失函数

3.1.1.3 解析解

一点点高数和线代知识

对以上求导,由于凸函数的性质,当导数为0时,损失最小,解的为

3.1.1.4 随机梯度下降

当没有解析解(显示解)时的优化方法

步长怎么找?

没看懂

3.1.2 矢量化加速

3.2 线性回归从零开始实现

生成数据集

X = torch.normal(0, 1, (num_examples, len(w)))

均值为0,方差为1,n个样本,列数为w

y += torch.normal(0, 0.01, y.shape)

同理,均值为0,方差为0.01,形状同y的长度

这里加的就是随机噪音,这段代码每次运行的结果都不一样

输出第一个样本

detach作用是把数据从计算图里面拎出来,然后再转numpy

读取数据集 

def data_iter(batch_size, features, labels):num_examples = len(features)          #确定样本数量indices = list(range(num_examples))   #range()表示从0 - n-1,list()表示转成list格式# 这些样本是随机读取的,没有特定的顺序random.shuffle(indices)               #把下标随机打乱for i in range(0, num_examples, batch_size):  #表示从0到n,每次跳batch_size个大小batch_indices = torch.tensor(indices[i: min(i + batch_size, num_examples)])yield features[batch_indices], labels[batch_indices] #每次产生随机特征和标号
batch_size = 10for X, y in data_iter(batch_size, features, labels):print(X, '\n', y)break

初始化模型参数

w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)  #requires_grad计算梯度
b = torch.zeros(1, requires_grad=True)  #1表示直接就是个标量,一个数,同样计算梯度

定义模型

def linreg(X, w, b):  #@save"""线性回归模型"""return torch.matmul(X, w) + b

定义损失函数

def squared_loss(y_hat, y):  #@save"""均方损失"""return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

定义优化算法

def sgd(params, lr, batch_size):  #params给定的所有参数,lr学习率,batch_size指的是批每次跳过的量"""小批量随机梯度下降"""with torch.no_grad():  #更新的时候不需要计算梯度for param in params:param -= lr * param.grad / batch_size #自动求导param.grad.zero_()

训练

lr = 0.03    #学习率
num_epochs = 3   #整个数据扫3遍
net = linreg   #之前定义的模型linreg,便于以后更换模型
loss = squared_loss    #均方损失for epoch in range(num_epochs):for X, y in data_iter(batch_size, features, labels):l = loss(net(X, w, b), y)  # X和y的小批量损失# 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,# 并以此计算关于[w,b]的梯度l.sum().backward()   #求和之后算梯度sgd([w, b], lr, batch_size)  # 使用参数的梯度更新参数with torch.no_grad():train_l = loss(net(features, w, b), labels)print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')#每一遍扫完后损失就会越来越小print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}') 

学习率小还能多跑几遍,学习率过大直接超出浮点运算范围了(nan=not a number)

3.3 线性回归的简洁实现

生成数据集

import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2ltrue_w = torch.tensor([2, -3.4])
true_b = 4.2                         #形成真实的w和b
features, labels = d2l.synthetic_data(true_w, true_b, 1000)

读取数据集

def load_array(data_arrays, batch_size, is_train=True):  #@save"""构造一个PyTorch数据迭代器"""dataset = data.TensorDataset(*data_arrays)return data.DataLoader(dataset, batch_size, shuffle=is_train)#每次从中挑选batch_size个数据出来,shuffle表示需不需要打乱顺序,is_train则表示需要batch_size = 10
data_iter = load_array((features, labels), batch_size)#如果已经有了features, labels,把它做成list,传到dataset
next(iter(data_iter))  #通过next函数得到x和y

定义模型

# nn是神经网络的缩写
from torch import nnnet = nn.Sequential(nn.Linear(2, 1))
#nn.Linear(2, 1)指的是输入维度为2,输出维度为1
#Sequential是一个容器,用来装层(层数多时非常有用)

初始化模型参数

net[0].weight.data.normal_(0, 0.01) #normal指使用正态分布替换掉data的值
net[0].bias.data.fill_(0)   #bias指偏差,这里直接置零

定义损失函数

loss = nn.MSELoss()   #MSELoss类

定义优化算法

trainer = torch.optim.SGD(net.parameters(), lr=0.03)
#net.parameters()包括所有参数,这里包括w和b

训练

num_epochs = 3   #迭代3个周期
for epoch in range(num_epochs):for X, y in data_iter:l = loss(net(X) ,y)trainer.zero_grad()   #trainer预设器梯度清零l.backward()          #计算backwardtrainer.step()        #调用step函数来更新模型l = loss(net(features), labels)print(f'epoch {epoch + 1}, loss {l:f}')w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)

3.4 softmax回归

分类和回归

回归是一个连续值(房价分析)

分类预测一个类别(手写数字识别)

分类输出的个数等于类别的个数

独热编码(one-hot encoding):

独热编码是一个向量,它的分量和类别一样多。 类别对应的分量设置为1,其他所有分量设置为0。 在我们的例子中,标签y将是一个三维向量, 其中(1,0,0)对应于“猫”、(0,1,0)对应于“鸡”、(0,0,1)对应于“狗”:

置信度:

【看完这篇就够了!!!通俗易懂】置信度理解(95%的置信度、置信区间)_醪糟小丸子的博客-CSDN博客_95%置信度

置信度:以测量值为中心,在一定范围内,真值出现在该范围内的几率。一般设定95%,是通常情况下置信度(置信水平)的设定值。
置信区间:在某一置信度下,以测量值为中心,真值出现的范围。一定概率下真值的取值范围(可靠范围)称为置信区间。其概率称为置信概率或置信度(置信水平)。

我的理解是

样本数目不变的情况下,做一百次试验,有95个置信区间包含了总体真值。置信度为95%

损失函数

L2 loss(均方损失)

正好在求导后抵消

L1 loss

预测值和真实值较远时,不管多远,梯度都是常数+/- 1

优点:稳定性好

缺点:零点是尖点,不可导。 优化到末期,结果会变得不稳定

Huber 's Robust Loss

预测值和真实值差距大时,绝对值大于1时,为绝对值误差,梯度为常数

预测值和真实值差距小时,误差函数像高斯函数,是线性的

这样兼具了L1 L2的优点

大概理解就是这样了

这里没怎么看懂,应该是基础知识欠缺的原因,等我学了概率论再来看

softmax:

想要使得输出是一个概率

y和^y的区别作为损失,此时所有都是概率

指数的好处在于无论是什么数都能变成非负

个人理解:softmax算出来的就是置信度

交叉熵:

没懂为啥这么算

一文搞懂交叉熵在机器学习中的使用,透彻理解交叉熵背后的直觉_史丹利复合田的博客-CSDN博客

额,还是没懂

3.5 图像分类数据集

MNIST数据集

Fashion-MNIST数据集

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2ld2l.use_svg_display()  #李沐老师写的包,用svg画图

读取数据集

# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式,
# 并除以255使得所有像素的数值均在0到1之间
trans = transforms.ToTensor()  #把图片转成张量
mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True) #把数据集下载到上一级目录的data里面,train=True表示下载的是训练数据集#transform=trans表示图片拿出来要是个pytorch的tensor#download=True表示默认从网上下载
mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)#mnist_test测试数据集,用来验证模型好坏#train=False 这就是说不下载训练数据集
len(mnist_train), len(mnist_test)  #图片数量mnist_train[0][0].shape
#mnist_train[][].shape 第一个[]表示第一个例子,第二个[]表示第一个图片
#这里试了一下发现好像都是黑白图片def get_fashion_mnist_labels(labels):  #@save"""返回Fashion-MNIST数据集的文本标签"""text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):  #@save"""绘制图像列表"""figsize = (num_cols * scale, num_rows * scale)_, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)axes = axes.flatten()for i, (ax, img) in enumerate(zip(axes, imgs)):if torch.is_tensor(img):# 图片张量ax.imshow(img.numpy())else:# PIL图片ax.imshow(img)ax.axes.get_xaxis().set_visible(False)ax.axes.get_yaxis().set_visible(False)if titles:ax.set_title(titles[i])return axesX, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))
#构建python的iterater(迭代器),用next取小批量
show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y));
#2,9表示画两行,每行9张图片

读取小批量

训练前要先看读取有多块,以读取速度来决定训练速度

读取速度要比训练速度快很多

batch_size = 256def get_dataloader_workers():  #@save"""使用4个进程来读取数据"""return 4train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=get_dataloader_workers())timer = d2l.Timer() #定义timer函数来测量速度
for X, y in train_iter:continue
f'{timer.stop():.2f} sec'

整合所有组件

def load_data_fashion_mnist(batch_size, resize=None):  #@save"""下载Fashion-MNIST数据集,然后将其加载到内存中"""trans = [transforms.ToTensor()]if resize:trans.insert(0, transforms.Resize(resize))trans = transforms.Compose(trans)mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)return (data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=get_dataloader_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False,num_workers=get_dataloader_workers()))train_iter, test_iter = load_data_fashion_mnist(32, resize=64)
for X, y in train_iter:print(X.shape, X.dtype, y.shape, y.dtype)break

3.6 softmax回归的从零开始实现

import torch
from IPython import display
from d2l import torch as d2lbatch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)#训练集和测试集的迭代器

初始化模型参数

num_inputs = 784  #先粗暴的把图片信息拉成向量28*28=784,损失掉的信息要用之后的神经网络
num_outputs = 10  #模型有10个类,所以输出维度为10W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)#size=(num_inputs, num_outputs)形状,行数为num_inputs 784,列数num_outputs 10
b = torch.zeros(num_outputs, requires_grad=True) #对于每一个输出都有偏移,长为num_outputs的向量

定义softmax操作

X = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])#2*3 的矩阵
X.sum(0, keepdim=True), X.sum(1, keepdim=True)#维度为0,列向量求和,得到行向量1*3;维度为1,行向量求和,得到列向量2*1def softmax(X):X_exp = torch.exp(X)partition = X_exp.sum(1, keepdim=True)return X_exp / partition  # 这里应用了广播机制#此时做一些验证
X = torch.normal(0, 1, (2, 5)) #两行五列的矩阵,且所有值都是正的
X_prob = softmax(X)
X_prob, X_prob.sum(1) #按行来加,每行和为1

定义模型

def net(X):return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)#-1表示自己算一下这里批量大小,之前设定过256,W.shape[0]=784#加偏移b是通过广播机制

定义损失函数

y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])#[0.1, 0.3, 0.6]为y0,[0.3, 0.2, 0.5]为y1
y_hat[[0, 1], y] #对第0样本拿出y0对应的元素,第1样本拿出y1对应的元素#所以最后输出值为0.1和0.5#y0拿出0对应的0.1,y1拿出2对应的0.5

感谢b站大学

def cross_entropy(y_hat, y):return - torch.log(y_hat[range(len(y_hat)), y])#生成长度n的向量,拿出真实标号的预测值cross_entropy(y_hat, y)  #这里求交叉熵
#y_hat是2*3的预测值,y是长为2的向量

分类精度

def accuracy(y_hat, y):  #@save"""计算预测正确的数量"""if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:y_hat = y_hat.argmax(axis=1) #每行元素值最大的那个下标存y_hat里cmp = y_hat.type(y.dtype) == y #把y_hat转成y的数据类型,然后作比较,变成bool型tensorreturn float(cmp.type(y.dtype).sum())accuracy(y_hat, y) / len(y)
#找出来预测正确的样本数,除以y的长度,求出预测正确的概率
#这里结果是0.5,因为都是随机生成的def evaluate_accuracy(net, data_iter):  #@save"""计算在指定数据集上模型的精度"""if isinstance(net, torch.nn.Module):net.eval()  # 将模型设置为评估模式metric = Accumulator(2)  # 正确预测数、预测总数with torch.no_grad():for X, y in data_iter:metric.add(accuracy(net(X), y), y.numel())#每次先把x放到net里算出评测值#accuracy(net(X), y)预测正确的样本数#这里求了总样本数return metric[0] / metric[1]#得到精度class Accumulator:  #@save"""在n个变量上累加"""def __init__(self, n):self.data = [0.0] * ndef add(self, *args):self.data = [a + float(b) for a, b in zip(self.data, args)]def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self, idx):return self.data[idx]evaluate_accuracy(net, test_iter)

由于都是随机生成,开始设置有10个类别,所以结果接近于0.1

训练

def train_epoch_ch3(net, train_iter, loss, updater):  #@save"""训练模型一个迭代周期(定义见第3章)"""# 将模型设置为训练模式if isinstance(net, torch.nn.Module):net.train()  #告诉pytorch,要计算梯度# 训练损失总和、训练准确度总和、样本数metric = Accumulator(3)  #长度为3的迭代器for X, y in train_iter:# 计算梯度并更新参数y_hat = net(X)l = loss(y_hat, y)  #交叉熵损失函数if isinstance(updater, torch.optim.Optimizer):#如果updater是pytorch中Optimizer,就先梯度置零# 使用PyTorch内置的优化器和损失函数updater.zero_grad()l.mean().backward()updater.step()  #自更新else:# 使用定制的优化器和损失函数l.sum().backward()   #先做求和再算梯度updater(X.shape[0])metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())# 返回训练损失和训练精度return metric[0] / metric[2], metric[1] / metric[2]#这里主要是画图,没看懂,再学学
class Animator:  #@save"""在动画中绘制数据"""def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,figsize=(3.5, 2.5)):# 增量地绘制多条线if legend is None:legend = []d2l.use_svg_display()self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)if nrows * ncols == 1:self.axes = [self.axes, ]# 使用lambda函数捕获参数self.config_axes = lambda: d2l.set_axes(self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)self.X, self.Y, self.fmts = None, None, fmtsdef add(self, x, y):# 向图表中添加多个数据点if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif not self.X:self.X = [[] for _ in range(n)]if not self.Y:self.Y = [[] for _ in range(n)]for i, (a, b) in enumerate(zip(x, y)):if a is not None and b is not None:self.X[i].append(a)self.Y[i].append(b)self.axes[0].cla()for x, y, fmt in zip(self.X, self.Y, self.fmts):self.axes[0].plot(x, y, fmt)self.config_axes()display.display(self.fig)display.clear_output(wait=True)def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):  #@save"""训练模型(定义见第3章)"""animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],legend=['train loss', 'train acc', 'test acc'])#可视化部分,以后再学for epoch in range(num_epochs):train_metrics = train_epoch_ch3(net, train_iter, loss, updater)#train_metrics训练误差test_acc = evaluate_accuracy(net, test_iter)#测试精度animator.add(epoch + 1, train_metrics + (test_acc,))#显示训练误差,训练精度;测试误差,测试精度train_loss, train_acc = train_metricsassert train_loss < 0.5, train_lossassert train_acc <= 1 and train_acc > 0.7, train_accassert test_acc <= 1 and test_acc > 0.7, test_acclr = 0.1def updater(batch_size):return d2l.sgd([W, b], lr, batch_size)num_epochs = 10
#训练十个迭代周期
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)

预测

def predict_ch3(net, test_iter, n=6):  #@save"""预测标签(定义见第3章)"""for X, y in test_iter:breaktrues = d2l.get_fashion_mnist_labels(y)  #真实标号preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1)) #预测标号titles = [true +'\n' + pred for true, pred in zip(trues, preds)] #转成字符串d2l.show_images(X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])predict_ch3(net, test_iter)

准确率挺高,

深度学习 笔记(线性神经网络)相关推荐

  1. July深度学习笔记之神经网络与反向传播算法

    July深度学习笔记之神经网络与反向传播算法 一.神经网络 神经网络的大致结构如下: 大致可以分为输入层.隐藏层与输出层. 而我们可以单独拿出来一个结点,可以发现,其实它就是类似一个逻辑回归(LR), ...

  2. 吴恩达深度学习笔记——卷积神经网络(Convolutional Neural Networks)

    深度学习笔记导航 前言 传送门 卷积神经网络(Convolutional Neural Networks) 卷积神经网络基础(Foundations of Convolutional Neural N ...

  3. 1.4)深度学习笔记------深层神经网络

    目录 1)Deep L-layer neural network 2)Forward Propagation in a Deep Network(重点) 3)Getting your matrix d ...

  4. 深度学习笔记——循环神经网络RNN/LSTM

    原文来自知乎专栏NLP进阶之路,作者韦伟. 以下文章是摘录了原文部分内容的学习笔记,侵删. 循环神经网络(Rerrent Neural Network) RNN是神经网络的一种,RNN对具有序列特性的 ...

  5. 吴恩达深度学习笔记(21)-神经网络的权重初始化为什么要随机初始化?

    随机初始化(Random+Initialization) 当你训练神经网络时,权重随机初始化是很重要的. 对于逻辑回归,把权重初始化为0当然也是可以的. 但是对于一个神经网络,如果你把权重或者参数都初 ...

  6. 吴恩达深度学习笔记——卷积神经网络(CNN)

    目录 一.计算机视觉(Computer vision) 二.边缘检测示例(Edge detection example) 三.更多的边缘检测内容(More edge detection) 四.Padd ...

  7. 深度学习笔记(九):神经网络剪枝(Neural Network Pruning)详细介绍

    文章目录 1:What is pruning 2:Pruning in MLP(多层感知机) 2.2 How to make mask 3.Pruning in CNN(卷积神经网络) 1:What ...

  8. 深度学习笔记:神经网络权重确定初始值方法

    神经网络权重不可为相同的值,比如都为0,因为如果这样网络正向传播输出和反向传播结果对于各权重都完全一样,导致设置多个权重和设一个权重毫无区别.我们需要使用随机数作为网络权重 实验程序 在以下实验中,我 ...

  9. Ng深度学习笔记-卷积神经网络-目标检测

    目标定位 符号表示: 图片左上角的坐标为(0,0)(0,0)(0,0),右下角标记为(1,1)(1,1)(1,1). 红色方框的中心点(bxb_{x}bx​,byb_{y}by​),边界框的高度为bh ...

  10. 深度学习笔记-卷积神经网络CNN与循环神经网络RNN有什么区别?

    转载 https://blog.csdn.net/weixin_35227692/article/details/79223536 转载于:https://www.cnblogs.com/USTBlx ...

最新文章

  1. java高级编程技巧
  2. java 按键框架,如何在java中更改框架?
  3. windows服务与网页交互_戴尔高级主动式触控笔-PN579X评测:Windows也有好触控
  4. Hadoop -- ES -- CURD
  5. 里面有面和点_鲜虾韭菜水晶饺,皮薄馅大,晶莹剔透,一不小心就变成了面点高手...
  6. 程序开发天团必备单品,稳定输出还加持千元商务礼限时送!
  7. nuget 是如何还原包的
  8. python字典的应用实验报告_Python字典应用的一个例子
  9. 每个日期新用户的次日留存率
  10. 高等代数——大学高等代数课程创新教材(丘维声)——2.6笔记+习题
  11. 库卡六轴机器人编程手册_KUKA机器人编程手册.pdf
  12. Java性能优化攻略详解
  13. 宝马CIC主机清FSC的方法步骤
  14. 获取网页标题的小图标
  15. Region Proposal by Guided Anchoring 笔记
  16. 苹果 python蚂蚁森林自动收能量_PythonAuto.js:实现蚂蚁森林自动收能量(懒人的高效生活)...
  17. 太阳能电池基本特性实验报告_太阳能电池基本特性研究实验报告
  18. 云服务器抢票咋用_可以利用云服务器来抢票不?
  19. 如何让浏览器直接下载后端返回的图片而不是打开
  20. uCLinux简介--

热门文章

  1. Phpstorm调试详解(包含命令行以及浏览器)
  2. Android 各种抓包工具抓包总结
  3. Git可视化工具-SourceTree
  4. springboot电竞俱乐部推荐系统
  5. SM4分组密码算法介绍
  6. UART串口DB9的连接
  7. python3 中英文标点转换
  8. 经典批处理教程(转)
  9. linux异步io 回调函数,Linux异步IO
  10. Shell脚本实现 ping功能