本章主要讲述数据预处理。
来源:动手学习深度学习(pytorch版)
数据预处理 1 2 3 4 5 6 7 8 9 10 import osos.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' )
1 2 3 import pandas as pddata=pd.read_csv(data_file) print (data)
NumRooms Alley Price
0 NaN Pave 127500
1 2.0 NaN 106000
2 4.0 NaN 178100
3 NaN NaN 140000
处理缺失值 1 2 3 4 5 inputs,outputs = data.iloc[:,0 :1 ],data.iloc[:,2 ] inputs = inputs.fillna(inputs.mean()) print (inputs)
NumRooms
0 3.0
1 2.0
2 4.0
3 3.0
1 2 3 inputs1=data.iloc[:,1 :2 ] inputs = pd.concat([inputs,inputs1],axis=1 ) inputs
NumRooms
Alley
0
3.0
Pave
1
2.0
NaN
2
4.0
NaN
3
3.0
NaN
我们将NaN视为一个类别,由于Alley列只接受两种类型的类别值Pave和NaN,pandas可以自动将此列转换为两列Alley_Pave和Alley_NaN 1 2 inputs = pd.get_dummies(inputs,dummy_na=True ,dtype=int ) 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
转换为张量格式 1 2 3 import torchX,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]))
线性代数 1 2 3 4 x = torch.tensor(3.0 ) y = torch.tensor(2.0 ) x + y, x * y, x / y, x**y
(tensor(5.), tensor(6.), tensor(1.5000), tensor(9.))
tensor([0, 1, 2, 3])
tensor(3)
4
torch.Size([4])
矩阵 1 2 A = torch.arange(20 ).reshape(5 ,4 ) A
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
tensor([[ 0, 4, 8, 12, 16],
[ 1, 5, 9, 13, 17],
[ 2, 6, 10, 14, 18],
[ 3, 7, 11, 15, 19]])
1 2 B = torch.tensor([[1 ,2 ,3 ],[2 ,0 ,4 ],[3 ,4 ,5 ]]) B , B == B.T
(tensor([[1, 2, 3],
[2, 0, 4],
[3, 4, 5]]),
tensor([[True, True, True],
[True, True, True],
[True, True, True]]))
张量 ##当我们处理图像时,张量将变得更加重要,图像以n维数组形式出现,其中3个轴对应于高度,宽度,以及一个通道用于表示颜色通道(红色,绿色和蓝色)。
1 2 X = torch.arange(24 ).reshape(2 ,3 ,4 ) X, len (X)
(tensor([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]]),
2)
张量算法的基本性质 1 2 3 A = torch.arange(20 ,dtype=torch.float32).reshape(5 ,4 ) B = A.clone() A, A + B
(tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]]),
tensor([[ 0., 2., 4., 6.],
[ 8., 10., 12., 14.],
[16., 18., 20., 22.],
[24., 26., 28., 30.],
[32., 34., 36., 38.]]))
tensor([[ 0., 1., 4., 9.],
[ 16., 25., 36., 49.],
[ 64., 81., 100., 121.],
[144., 169., 196., 225.],
[256., 289., 324., 361.]])
1 2 3 a = 2 X = torch.arange(24 ).reshape(2 ,3 ,4 ) a + X, (a * X).shape
(tensor([[[ 2, 3, 4, 5],
[ 6, 7, 8, 9],
[10, 11, 12, 13]],
[[14, 15, 16, 17],
[18, 19, 20, 21],
[22, 23, 24, 25]]]),
torch.Size([2, 3, 4]))
降维 1 2 x = torch.arange(4 ,dtype=torch.float32) x, x.sum ()
(tensor([0., 1., 2., 3.]), tensor(6.))
(torch.Size([5, 4]), tensor(190.))
1 2 3 A_sum_axis0=A.sum (axis=0 ) A_sum_axis0,A_sum_axis0.shape
(tensor([40., 45., 50., 55.]), torch.Size([4]))
1 2 A_sum_axis1 = A.sum (axis=1 ) A_sum_axis1, A_sum_axis1.shape
(tensor([ 6., 22., 38., 54., 70.]), torch.Size([5]))
tensor(190.)
1 A.mean(), A.sum () / A.numel()
(tensor(9.5000), tensor(9.5000))
1 A.mean(axis=0 ), A.sum (axis=0 ) / A.shape[0 ]
(tensor([ 8., 9., 10., 11.]), tensor([ 8., 9., 10., 11.]))
非降维求和 1 2 sum_A = A.sum (axis=1 ,keepdims=True ) sum_A
tensor([[ 6.],
[22.],
[38.],
[54.],
[70.]])
tensor([[0.0000, 0.1667, 0.3333, 0.5000],
[0.1818, 0.2273, 0.2727, 0.3182],
[0.2105, 0.2368, 0.2632, 0.2895],
[0.2222, 0.2407, 0.2593, 0.2778],
[0.2286, 0.2429, 0.2571, 0.2714]])
tensor([[ 0., 1., 2., 3.],
[ 4., 6., 8., 10.],
[12., 15., 18., 21.],
[24., 28., 32., 36.],
[40., 45., 50., 55.]])
点积 1 2 y = torch.ones(4 ,dtype = torch.float32) x, y, torch.dot(x,y)
(tensor([0., 1., 2., 3.]), tensor([1., 1., 1., 1.]), tensor(6.))
tensor(6.)
矩阵-向量积 1 2 A.shape, x.shape, torch.mv(A,x)
(torch.Size([5, 4]), torch.Size([4]), tensor([ 14., 38., 62., 86., 110.]))
矩阵-矩阵乘法
1 2 B = torch.ones(4 ,3 ) torch.mm(A,B)
tensor([[ 6., 6., 6.],
[22., 22., 22.],
[38., 38., 38.],
[54., 54., 54.],
[70., 70., 70.]])
范数 1 2 u = torch.tensor([3.0 ,-4.0 ]) torch.norm(u)
tensor(5.)
L1范数是取绝对值相加,L2范数是取平方相加后开平方,Lp范数是对每个值取p次方之后相加的和开p次方
tensor(7.)
费罗贝尼乌斯范数是矩阵元素平方和的平方根
1 torch.norm(torch.ones((4 ,9 )))
tensor(6.)
微积分 1 2 3 4 5 6 %matplotlib inline import numpy as npfrom matplotlib_inline import backend_inlinefrom d2l import torch as d2ldef f (x ): return 3 *x**2 -4 *x
1 2 3 4 5 6 def numerical_lim (f,x,h ): return (f(x+h)-f(x))/h h=0.1 for i in range (5 ): print (f'h={h:.5 f} ,numerocal limit = {numerical_lim(f,1 ,h):.5 f} ' ) h*=0.1
h=0.10000,numerocal limit = 2.30000
h=0.01000,numerocal limit = 2.03000
h=0.00100,numerocal limit = 2.00300
h=0.00010,numerocal limit = 2.00030
h=0.00001,numerocal limit = 2.00003
use_svg_display函数指定matplotlib包输出svg图表以获得更清晰的图像
@save是一个特殊的标记,会将对应的函数、类或语句保存在d2l包中 1 2 3 def use_svg_display (): """使用svg格式在jupyter中显示绘图""" backend_inline.set_matplotlib_formats('svg' )
1 2 3 4 def set_figsize (figsize=(3.5 ,2.5 ) ): """设置matplotlib的图表大小""" use_svg_display() d2l.plt.rcParams['figure.figsize' ] = figsize
1 2 3 4 5 6 7 8 9 10 11 12 def set_axes (axes,xlabel,ylabel,xlim,ylim,xscale,yscale,legend ): """设置matplotlib的轴""" axes.set_xlabel(xlabel) axes.set_ylabel(ylabel) axes.set_xscale(xscale) axes.set_yscale(yscale) axes.set_xlim(xlim) axes.set_ylim(ylim) if legend: axes.legend(legend) axes.grid()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def plot (X, Y=None ,xlabel=None ,ylabel=None ,legend=None ,xlim=None , ylim=None ,xscale='linear' ,yscale='linear' , fmts=('-' ,'m--' ,'g-.' ,'r:' ),figsize=(3.5 ,2.5 ),axes=None ): """绘制数据点""" if legend is None : legend = [] set_figsize(figsize) axes = axes if axes else d2l.plt.gca() def has_one_axis (X ): return (hasattr (X,"ndim" ) and X.ndim == 1 or isinstance (X,list ) and not hasattr (X[0 ],"__len__" )) if has_one_axis(X): X = [X] if Y is None : X, Y = [[]]*len (X),X elif has_one_axis(Y): Y = [Y] if len (X) != len (Y): X = X * len (Y) axes.cla() for x,y,fmt in zip (X,Y,fmts): if len (x): axes.plot(x,y,fmt) else : axes.plot(y,fmt) set_axes(axes,xlabel,ylabel,xlim,ylim,xscale,yscale,legend)
1 2 x = np.arange(0 ,3 ,0.1 ) plot(x,[f(x),2 *x-3 ],'x' ,'f(x)' ,legend=['f(x)' ,'Tangent line (x=1)' ])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import matplotlib.pyplot as pltdef f (x ): return x**3 -1 /x def f_tangent (f,x,point ): h=1e-4 grad=(f(h+point)-f(point))/h return grad*(x-point)+f(point) x=np.arange(0.1 ,2.0 ,0.01 ) y=f(x) y_tangent=f_tangent(f,x,1 ) plt.plot(x,y,label="f(x)" ) plt.plot(x,y_tangent,label="Tangent line at x=1" ) plt.legend() plt.title('Graph of f(x) and its tangent line at x=1' ) plt.xlabel('X' ) plt.ylabel('Y' ) plt.show()
1 2 3 x = torch.arange(2.0 ,requires_grad=True )
1 2 3 4 5 x = torch.ones(2 ,2 ,requires_grad=True ) print (x)print (x.grad_fn)
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
None
1 2 3 4 5 x = torch.ones(2 ,2 ,requires_grad=True ) y = x + 2 print (y)print (y.grad_fn)
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
<AddBackward0 object at 0x000002278E2D5D00>
is_leaf说明 注意像x是直接创建的,所以他没有grad_fn,而y是通过一个加法操作创建的,所以他有一个grad_fn 像x这种直接创建的称为叶子节点,叶子节点对应的grad_fn是None
1 print (x.is_leaf,y.is_leaf)
True False
1 2 3 4 5 6 7 8 9 10 a = torch.randn(2 ,2 ) print (a)a=((a*3 )/(a-1 )) print (a)print (a.requires_grad)a.requires_grad_(True ) y=(a*a).sum () print (y)print (y.requires_grad)
tensor([[ 0.5309, -0.5969],
[-0.9133, -1.4638]])
tensor([[-3.3949, 1.1214],
[ 1.4320, 1.7824]])
False
tensor(18.0100, grad_fn=<SumBackward0>)
True
1 2 3 4 5 6 7 8 9 10 x = torch.ones(2 ,2 ,requires_grad=True ) y = x+2 z = y*y*3 out = z.mean() print (z)print (out)out.backward() print (x.grad)
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>)
tensor(27., grad_fn=<MeanBackward0>)
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
grad_zero说明 该函数用来清除x的梯度,也就是重新赋值为0。需要注意的是,只有当x被求过一次梯度时,这个函数才能使用,否则会报错
1 2 3 4 5 6 7 8 9 10 out2 = x.sum () print (out2)out2.backward() print (x.grad)out3 = x.sum () x.grad.zero_() out3.backward() print (x.grad)
tensor(4., grad_fn=<SumBackward0>)
tensor([[5.5000, 5.5000],
[5.5000, 5.5000]])
tensor([[1., 1.],
[1., 1.]])