《动手学深度学习》第二章习题答案

《动手学深度学习》第二章地址:https://zh-v2.d2l.ai/chapter_preliminaries/index.html

2.1 练习

  1. 运行本节中的代码。将本节中的条件语句X == Y更改为X < YX > Y,然后看看你可以得到什么样的张量。

代码

X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
X>Y, X<Y

结果

(tensor([[False, False, False, False],
         [ True,  True,  True,  True],
         [ True,  True,  True,  True]]),
 tensor([[ True, False,  True, False],
         [False, False, False, False],
         [False, False, False, False]]))
  1. 用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果是否与预期相同?

代码

a = torch.arange(6).reshape((3, 1, 2))
b = torch.arange(2).reshape((1, 2, 1))
c = a + b
a.shape, b.shape, c.shape

结果

(torch.Size([3, 1, 2]), torch.Size([1, 2, 1]), torch.Size([3, 2, 2]))

可以看到结果与预期相同

2.2 练习

创建包含更多行和列的原始数据集。

生成数据

import os
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,Size\n')  # 列名,新增一列为Size
    f.write('NA,Pave,127500,100\n')  # 每行表示一个数据样本
    f.write('2,NA,106000,150\n')
    f.write('4,NA,178100,200\n')
    f.write('NA,NA,140000,NA\n')
    f.write('3,Pave,NA,NA\n') # 新增一行
  1. 删除缺失值最多的列。

代码

import pandas as pd
data = pd.read_csv(data_file)
data.isna().sum(axis=0)  # 查看缺失值最多的列, 缺失值最多的为Alley列
data.drop('Alley', axis=1, inplace=True)

结果

缺失值个数统计:

NumRooms    2
Alley       3
Price       1
Size        2
dtype: int64

删除缺失值最多的列后的数据

   NumRooms     Price   Size
0       NaN  127500.0  100.0
1       2.0  106000.0  150.0
2       4.0  178100.0  200.0
3       NaN  140000.0    NaN
4       3.0       NaN    NaN
  1. 将预处理后的数据集转换为张量格式

预处理的话,我们考虑前向后向填充,将缺失值填补上

代码

data = data.fillna(method='bfill')
data = data.fillna(method='ffill')
torch.tensor(data.values)

结果

tensor([[2.0000e+00, 1.2750e+05, 1.0000e+02],
        [2.0000e+00, 1.0600e+05, 1.5000e+02],
        [4.0000e+00, 1.7810e+05, 2.0000e+02],
        [3.0000e+00, 1.4000e+05, 2.0000e+02],
        [3.0000e+00, 1.4000e+05, 2.0000e+02]], dtype=torch.float64)

2.3 练习

  1. 证明一个矩阵 A 的转置的转置是A,即 (A^⊤)^⊤=A

对于A中的一个元素aij,其在第 i 行第 j 列,转置后出现在第 j 行第 i 列,再转置一次就出现在第 i 行第 j 列,又回到了原来的位置。所以,一个矩阵转置的转置还是它自己。

代码

import numpy as np
A = np.arange(12).reshape(3, 4)
A.T.T == A

结果

array([[ True,  True,  True,  True],
       [ True,  True,  True,  True],
       [ True,  True,  True,  True]])
  1. 给出两个矩阵 AB,证明“它们转置的和”等于“它们和的转置”,即 A^⊤+B^⊤=(A+B)^⊤

假设A第 i 行第 j 列的元素是 aij,B第 i 行第 j 列的元素是 bij。对于 A^T + B^T,其第 j 行第 i 列的值为 aij + bij;对于 (A + B)^T,其第 j 行第 i 列的值也为 aij + bij,推广至即可知A^T + B^T = (A + B)^T

代码

import numpy as np
A = np.arange(12).reshape(3, 4)
B = np.arange(12, 24).reshape(3, 4)
(A.T + B.T) == (A + B).T

结果

array([[ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True]])
  1. 给定任意方阵AA+A^⊤ 总是对称的吗?为什么?

是的,首先我们看一下对称矩阵的概念:
A 等于其转置:A=A^⊤,则称A为对称矩阵”。将 A+A^⊤看做一个整体,证明如下:
(A+A^T)^T = A^T + (A^T)^T = A^T + A

  1. 我们在本节中定义了形状 (2,3,4) 的张量Xlen(X)的输出结果是什么?

代码

X = torch.arange(24).reshape(2, 3, 4)
len(X)

结果

2
输出的是0轴的数值。

  1. 对于任意形状的张量X,len(X)是否总是对应于X特定轴的长度?这个轴是什么?

len(X) 总对应第 0 轴的长度,上题已回答。

  1. 运行A/A.sum(axis=1),看看会发生什么。你能分析原因吗?

会出错,原因在于A为5行4列的矩阵,维度为2,而A.sum(axis=1)则为长度为5的向量,二者无法相除,需要维度一致才会有广播机制,也就是我们需要设置keepdims=True

  1. 考虑一个具有形状 (2,3,4) 的张量,在轴0、1、2上的求和输出是什么形状?

课程中已讲过,对哪个轴求和,可以看作是压缩该维度,因此
轴0求和——>[3,4]
轴1求和——>[2,4]
轴2求和——>[2,3]
下面用代码验证一下

代码

X = torch.arange(24).reshape(2, 3, 4)
X.sum(axis=0).shape, X.sum(axis=1).shape, X.sum(axis=2).shape

结果

(torch.Size([3, 4]), torch.Size([2, 4]), torch.Size([2, 3]))
  1. 为linalg.norm函数提供3个或更多轴的张量,并观察其输出。对于任意形状的张量这个函数计算得到什么?

计算得到张量中所有值的 L2范数。
numpy.linalg.norm参数ord默认为None,此时对应的即为L2范数,见下表

ord norm for matrices norm for vectors
None Frobenius norm 2-norm

2.4 练习

书中的函数此处不再赘述

  1. 绘制函数 y=f(x)=x^3−\frac{1}x和其在 x=1处切线的图像。

先求导数:f'(x)=3x^2 +\frac {1}{x^2} 可得x=1时,f'(1)=4,又因为f(1) = 0
因此切线为4x-4

代码

x = np.arange(0.5, 1.5, 0.01)
plot(x, [x**3 - 1/x, 4*x-4], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])

结果

Figure_1.png
  1. 求函数 f(x)=3x_1^2+5e^{x2}的梯度。

[6x_1, 5e^{x_2}]

  1. 函数f(x)=∥X∥_2的梯度是什么?

∥X∥_2 = \sqrt{(x_1^2 + x_2^2 + ……x_n^2)} 先对x_1求导,可得:\frac {x_1} {\sqrt{(x_1^2 + x_2^2 + ……x_n^2)}}
同理类推:可得x_2、x_3……x_n
因此其梯度为:[\frac {x_1} {\sqrt{\sum{_{i=1}^nx_i^2}}}, \frac {x_2} {\sqrt{\sum{_{i=1}^nx_i^2}}},……,\frac {x_n} {\sqrt{\sum{_{i=1}^nx_i^2}}}]
简写为:\frac{X} {∥X∥_2}

  1. 你可以写出函数 u=f(x,y,z),其中 x=x(a,b)y=y(a,b)z=z(a,b) 的链式法则吗?

\frac{\partial u} {\partial a} = \frac{\partial u} {\partial x}\frac{\partial x} {\partial a}+\frac{\partial u} {\partial y}\frac{\partial y} {\partial a}+\frac{\partial u} {\partial z}\frac{\partial z} {\partial a}
\frac{\partial u} {\partial b} = \frac{\partial u} {\partial x}\frac{\partial x} {\partial b}+\frac{\partial u} {\partial y}\frac{\partial y} {\partial b}+\frac{\partial u} {\partial z}\frac{\partial z} {\partial b}

2.5 练习

  1. 为什么计算二阶导数比一阶导数的开销要更大?

因为计算二阶导数要在一阶导数的基础上再进行求导,开销肯定会更大。

  1. 在运行反向传播函数之后,立即再次运行它,看看会发生什么。

会发生运行错误,因为前向过程建立的计算图,会在反向传播后释放,所以第二次运行反向传播就会出错。这时在 backward 函数中加上参数 retain_graph=True(保持计算图),就能两次运行反向传播了。

代码

x = torch.arange(12., requires_grad=True)
y = 2 * torch.dot(x, x)
y.backward()
x.grad  #  tensor([ 0.,  4.,  8., 12., 16., 20., 24., 28., 32., 36., 40., 44.])
y.backward() # 会报错
  1. 在控制流的例子中,我们计算d关于a的导数,如果我们将变量a更改为随机向量或矩阵,会发生什么?

会发生运行错误,此处想说明的其实是pytorch中张量无法对张量求导,只能是标量对张量求导,因此如果我们将a修改为向量或矩阵,直接backward将会报错,需要对结果求和成一个标量后方能求导。

代码

a = torch.randn(size=(3,1), requires_grad=True)
d = f(a)
d.backward() # 直接运行这一步会报错
d.sum().backward() # 求和以后运行就没问题了
  1. 重新设计一个求控制流梯度的例子,运行并分析结果。

我们设计一个范数如果大于10,则返回梯度为2,否则返回梯度为1。以下为代码和结果

代码

def f(a):
    if a.norm() > 10:
        b = torch.dot(a, a)
    else:
        b = a
    return b.sum()
a1 = torch.arange(12., requires_grad=True)
a2 = torch.arange(2., requires_grad=True)
d1 = f(a1)
d2 = f(a2)
d1.backward()
d2.backward()
a1.grad, a2.grad

结果

(tensor([ 0.,  2.,  4.,  6.,  8., 10., 12., 14., 16., 18., 20., 22.]), # 范数大于10时,梯度为2
 tensor([1., 1.])) # 范数小于10时,梯度为1
  1. 使 f(x)=sin(x) ,绘制 f(x) 和 df(x)dx 的图像,其中后者不使用 f′(x)=cos(x) 。

代码

x = torch.linspace(-5, 5, 100)
x.requires_grad_(True)
y = torch.sin(x)
y.sum().backward()
y = y.detach()
d2l.plot(x.detach(), [y, x.grad], 'f(x)', "f'(x)", legend=['f(x)', 'Tangent line']) # 不采用cos(x),而使用x.grad
d2l.plt.show()

结果

Figure_1.png

2.6 练习

  1. 进行m=500组实验,每组抽取n=10个样本。改变mn,观察和分析实验结果。

书中已有m=500,n=10的结果,此处将m换为5000n换为20,查看结果

代码

import torch
from torch.distributions import multinomial
from d2l import torch as d2l
fair_probs = torch.ones([6]) / 6
counts = multinomial.Multinomial(20, fair_probs).sample((5000,))
cum_counts = counts.cumsum(dim=0)
estimates = cum_counts / cum_counts.sum(dim=1, keepdims=True)
d2l.set_figsize((6, 4.5))
for i in range(6):
    d2l.plt.plot(estimates[:, i].numpy(),
                 label=("P(die=" + str(i + 1) + ")"))
d2l.plt.axhline(y=0.167, color='black', linestyle='dashed')
d2l.plt.gca().set_xlabel('Groups of experiments')
d2l.plt.gca().set_ylabel('Estimated probability')
d2l.plt.legend()

结果

m=500,n=10 m=5000,n=20
1.png
2.png

对比以上结果可知,第二次的效果更好,更加趋近于 0.167。原因可能是第一张图实验组数为 500 组,而第二张图有 5000 组,实验组数越多,实验偏差就会分布的更加平均,效果就会更好。(此处对比试验最好将第二张图的n也设置为10,不过限于篇幅就不再展示了~大家可以下来多尝试)

  1. 给定两个概率为P(A)、P(B)的事件,计算P(A\cup B)P(A\cap B)的上限和下限。

P(A\cup B)上限为P(A)+P(B),下限为max(P(A),P(B))

image.png
上限 下限
2022-01-06 11-41-51 的屏幕截图.png
2022-01-06 11-42-04 的屏幕截图.png

P(A\cap B)上限为min(P(A),P(B)),下限为0

image.png

上限 下限
2022-01-06 11-44-33 的屏幕截图.png
2022-01-06 11-44-59 的屏幕截图.png
  1. 假设我们有一系列随机变量,例如ABC ,其中 B 只依赖于 A ,而 C 只依赖于 B ,你能简化联合概率 P(A,B,C) 吗?

根据题意可得:A,B,C满足马尔科夫链A——>B——>C 下面开始推导
P(A,B,C)=P(C|A,B)P(A,B)=P(C|A,B)P(B|A)P(A)
其中P(C|A,B)=P(C|B) =====>马尔科夫链
因此最终化简为:P(C|B)P(B|A)P(A)

  1. 在 2.6.2.6节中,第一个测试更准确。为什么不运行第一个测试两次,而是同时运行第一个和第二个测试?

原因是如果进行两次第一种测试,两次测试没有条件独立性,不能使用上面的公式进行计算,而且两次测试结果大概率相同,效果并不好。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容