原书链接:《动手学深度学习》 — 动手学深度学习 2.0.0 documentation (d2l.ai)
本人初次接触python,主要用于记录自己在学习本书时遇到的问题。可能解决办法还有很多种,也希望各位多多指教!也肯定会有许多地方不专业,也希望多多海涵。
安装
anaconda3安装教程于基本使用指令:Anaconda详细安装及使用教程(带图文) - 知乎 (zhihu.com)
初次接触时,在安装anaconda3时遇见了创建环境失败的问题。尝试过使用cd命令在指定目录下创建环境,但是依然无法创建环境。后怀疑是因为使用的清华源下载的anaconda3导致无法使用书中代码创建环境。尝试换回默认源后,环境顺利创建。
与JetBrains PyCharm 连接时,PyCharm无法在加载解释器中找到anaconda。后来查看网上帖子得知,这种情况下一般可以在这下载好的anaconda的目录中这个路径找到Python解释器,并添加上。F:\ProgramData\anaconda3\Scripts
之后按照书中提示输入对应代码就可以下载d2l包了
2.预备知识
2.2.数据预处理
在这一节中练习部分需要删除缺失值最多的列。作为初接触python的小白,当然不会。但在下面的论坛中发现了分享的答案代码。
import os
import pandas
def drop_col(m):
num = m.isna().sum() # 获得缺失值统计信息
print(num)
num_dict = num.to_dict() # 转为字典
print(num_dict)
max_key = max(num_dict, key=num_dict.get) # 取字典中最大值的键
# print(max_key)
del m[max_key] # 删除缺失值最多的列
return m
os.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n') # 列名
f.write('NA,Pave,127500\n') # 每行表示一个数据样本
f.write('2,NA,106000\n')
f.write('4,NA,178100\n')
f.write('NA,NA,140000\n')
data = pandas.read_csv(data_file)
print(data)
drop_col(data)
print(data)
结果:
2.4.微积分
在这节中需要画图,但是程序是在pycharm中运行是看不到图像的,需要添加一行如下代码才能正常出图。就目前自己学进度来说,只要是关于出图片的代码,都需要加一行这个代码。
d2l.plt.show()
3.线性神经网络
3.1线性回归
3.1.1.线性回归的基本元素
3.1.1.1.线性模型
当教学线性神经网络的时候,通常可以看到如下的公式和图片:
其中X可以表示为咱门神经网络需要输入的特征数据,W是每个特征数据的权重,b是偏移量,o是神经网络的输出结果。可以理解为矩阵向量之间的运算。
3.1.1.2.损失函数
损失函数主要用于预估咱们模型的质量。假设是真实值,是估计值,我们就可以比较。
将这个算式称为平方损失,神经网络中会根据产生的损失不断的去更新我们的未知参数(如线性回归模型中的权重W和偏移量b)。
3.1.1.3.解析解
当损失函数的值取到最小值的时候就可以达到预测值与实际值接近的时候。所有我们需要对损失函数求导数。即:
就可以通过上式解出W的值,使神经网络的输出值更接近真实值。
3.1.1.4.随机梯度下降
一般实际的情况中大多数的损失函数会存在不可导的情况,所以无法直接通过求导找出最优解,因此通过逐步接近的方法找到最优解。
上式中,是学习率,可以由我们自行设置。但选择学习率不可以过大和过小,否则会造成产生NaN和inf的情况。
3.2线性回归的从零开始实现
在这一章中,因为代码都是自己敲的,所以漏掉了一个变量(batch_size)。
导致运行结果出现了这个样子。
个人理解,由于没有batch_size,导致range函数在运行时是以增量为1的进度取,以至于一轮拿到了很充足的数据,导致第一轮的损失函数的结果很低。所以,细心真的很重要!也希望有大佬可以和我讲解一下具体原因。
3.4.softmax回归
3.4.1.分类问题
采用独热编码去表示类别。独热编码是一个向量,它的分量和类别一样多。类别对应的地方设置为1,其他地方设置为0。例如:有三个类别分别是{狗、猫、鸡}。其中(1,0,0)对应于狗,(0,1,0)对应于猫,(0,0,1)对应于鸡。
3.4.2.网络构架
softmax回归的网络构架可以简单理解为线性回归模型的Plus版本。相对于线性回归的多输入、单输出的模型变成了多输入、多输出的模型。
用公式可以表示为:
有没有感觉这样的表示很熟悉呢?没错,其实该模型的本质可以理解成矩阵。
3.5.图像分类数据集
3.5.1. 读取数据集
在书中有实现展示训练集部分图片的代码,如:
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));
依然还是需要在Pycharm中添加代码才能正常展示图片。
d2l.plt.show()
3.6.softmax回归的从零开始实现
3.6.5.分类精度
本小节主要记录自己初次看不懂而后理解的代码。
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)
cmp = y_hat.type(y.dtype) == y
return float(cmp.type(y.dtype).sum())
第一行代码 len(y_hat.shape) > 1用于判断预计数据的组别是否大于1,等价于y_hat.shape[0] > 1。y_hat.shape[1] > 1用于判断预计数据的类别是否大于1。如果满足条件,那么将每行的最大值标号拿出并与真实值进行比较,如于真实值一致记为1,反之记为0。并将结果加起来返回出去。通过如下代码就可以求出本次的准确率了。
accuracy(y_hat, y) / len(y)
在编写实现画图功能的代码时,发现在pychorm中无法展示动画过程。需要在原代码的基础上加入两行代码便可以恢复功能。
class Animator:
"""在动画中绘制数据"""
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, fmts
def add(self, x, y):
# 向图表中添加多个据点
if not hasattr(y, "__len__"):
y = [y]
n = len(y)
if not hasattr(x, "__len__"):
x = [x] * n
if 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)
d2l.plt.draw() #
d2l.plt.pause(0.001) #
display.clear_output(wait=True)
带#的代码就是新添加上的代码。在本书之后的程序中,还需要显示动画的代码是没有动画效果的,原因也和这里一样,需要将d2l包中的 class Animator 的源代码加上上面添加的代码即可实现动画化。但是动画的更新效果差,其实不用展示动画也可以正常使用。
3.6.7.预测
def predict_ch3(net, test_iter, n=6): #@save
"""预测标签(定义见第3章)"""
for X, y in test_iter:
break
trues = 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)
这一段代码在运行的时候仅仅只能提取前6幅固定的图片进行预测,原因是在导入测试集的代码中并没有随机排序,后续进行预测的代码也没有更新测试集导致。
所以我在预测前更新训练集的代码便可以产生和书中不一样的结果了。
很明显,这组测试中第二张那个图片分类错误,这属于正常现象,因为这套模型训练达到的精度只有80%左右。