波波算法笔记

Bob Peng

动手学深度学习v2学习篇预备知识一

2025-04-01
动手学深度学习v2学习篇预备知识一

《动手学深度学习》v2学习篇--预备知识(一)

前言

嘿!这里是笔者的《动手学深度学习》v2学习篇,最近一段时间由于工作需要,目前在深度学习“深度学习”,以下皆为学习笔记与思考的分享。欢迎指正与follow。

本次分享:数据基本操作

torch数据创建你会发现与numpy非常相似,张量(tensor)也可以类比为(ndarray)。当然他们并不相同。对于torch,GPU很好地支持加速计算,而NumPy仅支持CPU计算;张量类支持自动微分。使得张量类更适合深度学习

导入torch

import torch  #导入torch

数据创建

torch.arange(12)   
  
#向量包含以0开始的前12个整数


torch.zeros((2, 3, 4))   
  
#形状为(2,3,4)的张量,其中所有元素都设置为0  



torch.ones((2, 3, 4))  
  
#形状为(2,3,4)的张量,其中所有元素都设置为1  



torch.randn(3, 4)   
  
#形状为(3,4)的张量,每个元素都从均值为0、标准差为1的标准高斯分布中随机采样


torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])   
  
#Python列表(也可以是nparray类型),赋予张量确定值

张量属性

torch.arange(12)   
  
x.shape    
  
#结果:torch.Size([12])


x.numel()   
  
#结果:12


X = x.reshape(3, 4)  
  
#改变张量的形状,张量的大小不会改变

简单运算

以下 加、减、乘、除、求幂都是两个张量同一位置元素进行运算。**是求幂

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.]))

张量连结

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)

这里的dim可以理解为维度,dim=0,第0个维度(这里是指行向量方向)方向堆叠,

(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.]]))

广播机制

a = torch.arange(3).reshape((3, 1))  
b = torch.arange(2).reshape((1, 2))  
a, b


(tensor([[0],  
         [1],  
         [2]]),  
 tensor([[0, 1]]))

不同形状张量相加

a + b  

由于a和b形状不同,如果让它们相加,它们的形状不匹配。我们将两个矩阵广播为一个更大的 矩阵,如下所示:矩阵a将复制列, 矩阵b将复制行,然后再按元素相加。

tensor([[0, 1],  
        [1, 2],  
        [2, 3]])

索引与切片

张量[ ]里的“ ,”用来分割不同维度的切片取值,没有就是指第一个维度。

X[-1], X[1:3]  
# 访问最后一行, 访问第1行和第2行

修改

X[0:2, :] = 12  
  
# 0、1行的所有值改为12


X[1, 2] = 9  
  
#第一维度为1,第二维度为2所得到的值

内存问题

id()可以理解为c++里的找指针,就是数据在内存中的的地址

before = id(Y)  
Y = Y + X  
id(Y) == before  
  
答案是False

节省内存—原地更新(以下例子)

Z = torch.zeros_like(Y)  
print('id(Z):', id(Z))  
Z[:] = X + Y  
print('id(Z):', id(Z))  
  
地址一致


before = id(X)  
X += Y  
id(X) == before  
  
地址一致

数据预处理

大多数情况,我们的数据并不是直接的数字,而是保存在各种格式的文件里的数字,文字等,甚至存在缺失值。我们需要进行处理,转换成张量。

比如

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\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')


import pandas as pd  
  
data = 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

缺失值处理

**为了处理缺失的数据,典型的方法包括 插值法 和 删除法 , ** 其中插值法用一个替代值弥补缺失值,而删除法则直接忽略缺失值。在(
这里,我们将考虑插值法 )。

iloc先考虑列再其次是行,这里利用已有数据的平均值填充NAN

inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]  
inputs = inputs.fillna(inputs.mean(numeric_only=True))


inputs = pd.get_dummies(inputs, dummy_na=True)

转为numpy再转为tensor

import torch  
  
X = torch.tensor(inputs.to_numpy(dtype=float))  
y = torch.tensor(outputs.to_numpy(dtype=float))  
  
X, y

结果如下:

(array([[3., 1., 0.],  
        [2., 0., 1.],  
        [4., 0., 1.],  
        [3., 0., 1.]], dtype=float64),  
 array([127500., 106000., 178100., 140000.], dtype=float64))

下一次分享:线性代数、微积分、微分、概率。