深度学习环境安装
在之前做数据分析就已经安装过anaconda,所以不安装miniconda
安装完成之后,由于国内的pip太慢,所以要更换镜像源
上海交通大学 Linux 用户组 软件源镜像服务 (sjtu.edu.cn)
然后经过一些配置之后
安装git也弄过了
国内git速度巨慢无比,加速在此GitHub Proxy 代理加速 (ghproxy.com)
数学基础学习了高等数学中的微积分模块与对于梯度的学习,链式法则,补习了线代范式内容,后续会更新数学笔记
课程环境搭建
已搭建成功
准备工作
数据操作
张量
张量表示一个由数值组成的数组,这个数组可能有多个维度。 具有一个轴的张量对应数学上的向量(vector); 具有两个轴的张量对应数学上的矩阵(matrix); 具有两个轴以上的张量没有特殊的数学名称。
一维张量 对应向量
二维张量 对应矩阵
三维以及以上不命名
重要函数
reshape
要想改变一个张量的形状而不改变元素数量和元素值,可以调用reshape
函数。 例如,可以把张量x
从形状为(12,)的行向量转换为形状为(3,4)的矩阵。 这个新的张量包含与转换前相同的值,但是它被看成一个3行4列的矩阵。 要重点说明一下,虽然张量的形状发生了改变,但其元素值并没有变。 注意,通过改变张量的形状,张量的大小不会改变。
x = torch.arange(12)
x
X = x.reshape(3, 4)
X
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
我们不需要通过手动指定每个维度来改变形状。 也就是说,如果我们的目标形状是(高度,宽度), 那么在知道宽度后,高度会被自动计算得出,不必我们自己做除法。 在上面的例子中,为了获得一个3行的矩阵,我们手动指定了它有3行和4列。 幸运的是,我们可以通过-1
来调用此自动计算出维度的功能。 即我们可以用x.reshape(-1,4)
或x.reshape(3,-1)
来取代x.reshape(3,4)
。
zeros,ones,randn
有时,我们希望使用全0、全1、其他常量,或者从特定分布中随机采样的数字来初始化矩阵。 我们可以创建一个形状为(2,3,4)的张量,其中所有元素都设置为0。代码如下:
torch.zeros((2, 3, 4))
torch.ones((2, 3, 4))
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
tensor([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])
有时我们想通过从某个特定的概率分布中随机采样来得到张量中每个元素的值。 例如,当我们构造数组来作为神经网络中的参数时,我们通常会随机初始化参数的值。 以下代码创建一个形状为(3,4)的张量。 其中的每个元素都从均值为0、标准差为1的标准高斯分布(正态分布)中随机采样。
torch.randn(3, 4)
tensor([[ 0.7277, -1.3848, -0.2607, 0.9701],
[-2.3290, -0.3754, 0.2457, 0.0760],
[-1.2832, -0.3600, -0.3321, 0.8184]])
运算
张量可以直接通过运算符直接按元素计算
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y
(tensor([ 3., 4., 6., 10.]),
tensor([-1., 0., 2., 6.]),
tensor([ 2., 4., 8., 16.]),
tensor([0.5000, 1.0000, 2.0000, 4.0000]),
tensor([ 1., 4., 16., 64.]))
还可以通过函数连结在一起,连结时选择参数,按照轴0还是轴1,按照轴0就是按行结合,1是按照列结合
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]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)
(tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 2., 1., 4., 3.],
[ 1., 2., 3., 4.],
[ 4., 3., 2., 1.]]),
tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],
[ 4., 5., 6., 7., 1., 2., 3., 4.],
[ 8., 9., 10., 11., 4., 3., 2., 1.]]))
还可以通过逻辑运算符来获得特殊张量
X == Y
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
在某些情况下,即使形状不同,我们仍然可以通过调用 广播机制(broadcasting mechanism)来执行按元素操作。 这种机制的工作方式如下(就是逐行去逐列进行计算):
1.通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状;
2.对生成的数组执行按元素操作。
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a, b
a + b
(tensor([[0],
[1],
[2]]),
tensor([[0, 1]]))
tensor([[0, 1],
[1, 2],
[2, 3]])
索引跟切片与普通列表大差不差,所以不对其再进行论述
节省内存
一些操作可能会导致新结果分配新的内存,在对大量数据进行操作时,会占用很大的存储空间,故采用方法进行规避
before = id(Y)
Y = Y + X
id(Y) == before
False
综上,这样加合的习惯会带来不小的麻烦,我们采取原地操作
执行原地操作非常简单。 我们可以使用切片表示法将操作的结果分配给先前分配的数组
如果在后续计算中没有重复使用X
, 我们也可以使用X[:] = X + Y
或X += Y
来减少操作的内存开销。
数据预处理
在学习中,我们要使用pandas
预处理原始数据,并将原始数据转换为张量格式
首先我们无论自己手动编写,还是外界下载,要得到一个CSV格式的文件
通过pandas的read_csv
函数对数据进行格式转化
pandas.read_csv(文件)
处理缺失值
在数据处理中,会有一些值由于某种原因缺失,这种情况下我们要对其进行一定的处理。通常用的有两种方法,插值法和删除法, 其中插值法用一个替代值弥补缺失值,而删除法则直接忽略缺失值。 在这里,我们将考虑插值法。
例如这样的一个表
NumRooms Alley Price
0 NaN Pave 127500
1 2.0 NaN 106000
2 4.0 NaN 178100
3 NaN NaN 140000
通过位置索引iloc
,我们将data
分成inputs
和outputs
, 其中前者为data
的前两列,而后者为data
的最后一列。 对于inputs
中缺少的数值,我们用同一列的均值替换“NaN”项。
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean())
print(inputs)
NumRooms Alley
0 3.0 Pave
1 2.0 NaN
2 4.0 NaN
3 3.0 NaN
对于inputs
中的类别值或离散值,我们将“NaN”视为一个类别。 由于“巷子类型”(“Alley”)列只接受两种类型的类别值“Pave”和“NaN”, pandas
可以自动将此列转换为两列“Alley_Pave”和“Alley_nan”。 巷子类型为“Pave”的行会将“Alley_Pave”的值设置为1,“Alley_nan”的值设置为0。 缺少巷子类型的行会将“Alley_Pave”和“Alley_nan”分别设置为0和1。
inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
NumRooms Alley_Pave Alley_nan
0 3.0 1 0
1 2.0 0 1
2 4.0 0 1
3 3.0 0 1
现在inputs
和outputs
中的所有条目都是数值类型,它们可以转换为张量格式。
import torch
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
X, y
(tensor([[3., 1., 0.],
[2., 0., 1.],
[4., 0., 1.],
[3., 0., 1.]], dtype=torch.float64),
tensor([127500, 106000, 178100, 140000]))