《动手学深度学习(PyTorch版)》2、线性神经网络
本帖最后由 xinmeng_wit 于 2024-9-26 20:44 编辑<p><strong><span style="font-size:18px;">一、线性回归</span></strong></p>
<p><em>回归</em>(regression)是能为一个或多个自变量与因变量之间关系建模的一类方法。 在自然科学和社会科学领域,回归经常用来表示输入和输出之间的关系。</p>
<p>在机器学习领域中的大多数任务通常都与<em>预测</em>(prediction)有关,但不是所有的<em>预测</em>都是回归问题。</p>
<p>线性回归应该大家都比较熟悉了,其数学表达式为:</p>
<div style="text-align: left;"></div>
<p>向量x对应于单个样本的特征,w表示权重,b表示偏置。</p>
<p>也就是将输入的特征x通过线性方程得到估计的输出值。</p>
<p> </p>
<ul>
<li><strong><span style="font-size:16px;">损失函数</span></strong></li>
</ul>
<p>既然由线性方程得到的是估计值,那么就需要一种方法来评估这个估计值与实际值的接近程度,这个方法就是损失函数。</p>
<p><em>损失函数</em>(loss function)能够量化目标的<em>实际</em>值与<em>预测</em>值之间的差距。 通常我们会选择非负数作为损失,且数值越小表示损失越小,完美预测时的损失为0。 回归问题中最常用的损失函数是平方误差函数。</p>
<p>平方误差可以定义为:</p>
<div style="text-align: left;"></div>
<p><img alt="\hat{y}" src="https://bbs.eeworld.com.cn/gif.latex?%5Chat%7By%7D" />为预测值,y为实际值。</p>
<p>常数1/2不会带来本质的差别,但这样在形式上稍微简单一些 (因为当我们对损失函数求导后常数系数为1)</p>
<div style="text-align: left;"></div>
<p>在训练模型时,我们希望寻找一组参数(w,b), 这组参数能最小化在所有训练样本上的总损失。</p>
<p>特别的一点是像线性回归这样的简单问题存在解析解,但并不是所有的问题都存在解析解。 解析解可以进行很好的数学分析,但解析解对问题的限制很严格,导致它无法广泛应用在深度学习里。</p>
<p> </p>
<ul>
<li><span style="font-size:16px;"><strong>随机梯度下降</strong></span></li>
</ul>
<p>即使在我们无法得到解析解的情况下,我们仍然可以有效地训练模型。</p>
<p>我们用到一种名为<em>梯度下降</em>(gradient descent)的方法, 这种方法几乎可以优化所有深度学习模型。 它通过不断地在损失函数递减的方向上更新参数来降低误差。</p>
<p>梯度下降最简单的用法是计算损失函数(数据集中所有样本的损失均值) 关于模型参数的导数(在这里也可以称为梯度)。 但实际中的执行可能会非常慢:因为在每一次更新参数之前,我们必须遍历整个数据集。 因此,我们通常会在每次需要计算更新的时候随机抽取一小批样本, 这种变体叫做<em>小批量随机梯度下降</em>(minibatch stochastic gradient descent)。</p>
<p>在每次迭代中,我们首先随机抽样一个小批量B, 它是由固定数量的训练样本组成的。 然后,我们计算小批量的平均损失关于模型参数的导数(也可以称为梯度)。 最后,我们将梯度乘以一个预先确定的正数η,并从当前参数的值中减掉。</p>
<p>我们用下面的数学公式来表示这一更新过程(∂表示偏导数):</p>
<div style="text-align: left;"></div>
<p> </p>
<p><span style="font-size:18px;"><strong>二、softmax回归</strong></span></p>
<p>前面介绍了线性回归,回归可以用于预测<em>多少</em>的问题。 比如预测房屋被售出价格,或者棒球队可能获得的胜场数,又或者患者住院的天数。</p>
<p>事实上,我们也对<em>分类</em>问题感兴趣:不是问“多少”,而是问“哪一个”。</p>
<p>softmax回归的出现就能帮助我们解决分类相关的问题。</p>
<p>softmax函数额表达式如下:</p>
<div style="text-align: left;"></div>
<p>尽管softmax是一个非线性函数,但softmax回归的输出仍然由输入特征的仿射变换决定。 因此,softmax回归是一个<em>线性模型</em>(linear model)。</p>
<p>softmax的损失函数如下:</p>
<div style="text-align: left;"></div>
<p> </p>
<p><strong><span style="font-size:18px;">三、图像分类数据集</span></strong></p>
<p>MNIST数据集 (<a href="https://zh-v2.d2l.ai/chapter_references/zreferences.html#id90" title="LeCun, Y., Bottou, L., Bengio, Y., Haffner, P., & others. (1998). Gradient-based learning applied to document recognition. Proceedings of the IEEE, 86(11), 2278–2324.">LeCun <em>et al.</em>, 1998</a>) 是图像分类中广泛使用的数据集之一,但作为基准数据集过于简单。 我们将使用类似但更复杂的Fashion-MNIST数据集 (<a href="https://zh-v2.d2l.ai/chapter_references/zreferences.html#id189" title="Xiao, H., Rasul, K., & Vollgraf, R. (2017). Fashion-mnist: a novel image dataset for benchmarking machine learning algorithms. arXiv preprint arXiv:1708.07747.">Xiao <em>et al.</em>, 2017</a>)。</p>
<p>Fashion-MNIST由10个类别的图像组成, 每个类别由<em>训练数据集</em>(train dataset)中的6000张图像 和<em>测试数据集</em>(test dataset)中的1000张图像组成。 因此,训练集和测试集分别包含60000和10000张图像。 测试数据集不会用于训练,只用于评估模型性能。</p>
<p>每个输入图像的高度和宽度均为28像素。 数据集由灰度图像组成,其通道数为1。 为了简洁起见,本书将高度h像素、宽度w像素图像的形状记为h×w或(h,w)。</p>
<p>Fashion-MNIST中包含的10个类别,分别为t-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)。 以下函数用于在数字标签索引及其文本名称之间进行转换。</p>
<p>数据集的加载及可视化代码如下:</p>
<pre>
<code class="language-python">
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l
d2l.use_svg_display()
# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式,
# 并除以255使得所有像素的数值均在0~1之间
trans = transforms.ToTensor()
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)
len(mnist_train), len(mnist_test)
def get_fashion_mnist_labels(labels):#@save
"""返回Fashion-MNIST数据集的文本标签"""
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return 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)
return axes
X, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))
show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y))
d2l.plt.show()
batch_size = 256
def get_dataloader_workers():#@save
"""使用4个进程来读取数据"""
return 4
train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,
num_workers=get_dataloader_workers())
def load_data_fashion_mnist(batch_size, resize=None):#@save
"""下载Fashion-MNIST数据集,然后将其加载到内存中"""
trans =
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</code></pre>
<p>运行结果:</p>
<div style="text-align: left;"></div>
<p>后面将基于该数据集做分类相关的实验,本次就先到这里。</p>
<p> </p>
<p> </p>
页:
[1]