深度学习——数据操作

文章目录

1. 引言

为了能够完成各种数据操作,我们需要某种方法来存储和操作数据。

通常,我们需要做两件重要的事:(1)获取数据;(2)将数据读入计算机后对其进行处理。

2. n维数组(也称为张量 tensor)

张量机器学习神经网络 的主要数据结构

例子:

0维张量(只有一个元素) 俗称为 标量,常用于表示样本的类别

1维张量(只有一行) 称为 (特征)向量,可以用于表示一个样本的特征
请添加图片描述

**注:**jpg格式的图片为3通道,而png格式的图片是四通道
请添加图片描述

3. PyTorch 基本使用

**注:**它虽然被称为 PyTorch,但代码中导入时应是 torch

1. 张量的创建

1. torch.tensor() 根据指定数据创建张量

1. 创建张量标量(传入一个值)
data = torch.tensor(10)
data	# tensor(10)
2. 传入 numpy 数组, 由于 data 为 float64, 下面代码也使用该类型
ndarray = np.random.randn(2, 3)
data = torch.tensor(ndarray)
data	# tensor([[-0.3198,  0.1038, -0.2568],
        # 		  [ 1.5417, -0.0497, -0.6989]], dtype=torch.float64)
3. 传入列表, 下面代码使用默认元素类型 float32
list1 = [[10., 20., 30.], [40., 50., 60.]]
data = torch.tensor(list1)
data	# tensor([[10., 20., 30.],
        # 		  [40., 50., 60.]])

2. torch.Tensor() 根据指定形状创建张量,也可以用来创建指定数据的张量

1. 创建2行3列的张量, 默认 dtype 为 float32
data = torch.Tensor(2, 3)
data	# tensor([[9.1837e-39, 8.4490e-39, 9.6428e-39],
        # 		  [8.4490e-39, 1.0194e-38, 9.4592e-39]])
2. 注意: 如果传递列表, 则创建包含指定元素的张量
data = torch.Tensor([10])
data	# tensor([10.])
data = torch.Tensor([10, 20])
data	# tensor([10., 20.])

3. 创建指定类型的张量

1. 创建2行3列, dtype 为 int32 的张量
data = torch.IntTensor(2, 3)
data	# tensor([[1684432176,  758200116, 1717974627],
        # 		  [ 875639853, 1667378530,  808269669]], dtype=torch.int32)
2. 注意: 如果传递的元素类型不正确, 则会进行类型转换
data = torch.IntTensor([2.5, 3.3])
data	# tensor([2, 3], dtype=torch.int32)
3. 转换成其他的类型
data = torch.ShortTensor() 		# int16
# data = torch.LongTensor() 	# int64
# data = torch.FloatTensor() 	# float32
# data = torch.DoubleTensor() 	# float64
data

4. 创建线性张量

1. torch.arange() 在指定区间按照步长生成元素 (start, end, step):左闭右开[start,end)
data = torch.arange(0, 10, 2)
data	# tensor([0, 2, 4, 6, 8])
2. torch.linspace() 在指定区间按照元素个数生成 (start, end, steps):左闭右闭[start,end]
data = torch.linspace(0, 9, 10)
data	# tensor([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

5. 创建随机张量

1. torch.randn() 创建随机张量
# 1. 创建随机张量
data = torch.randn(2, 3) # 创建2行3列张量
print(data)	# tensor([[-1.5035, -1.2893,  0.7983],
        	# 		  [ 0.8991,  0.6286,  0.8412]])
2. torch.random.initial_seed():获取随机数据种子
# 2. 查看随机数种子
print('随机数种子:', torch.random.initial_seed())	# 随机数种子: 19252
3. torch.random.manual_seed():设置随机数据种子
# 3. 随机数种子设置	设置随机数种子后即:伪随机,生成的都是固定的
torch.random.manual_seed(100)
data = torch.randn(2, 3)
print(data)
print('随机数种子:', torch.random.initial_seed())

"""
tensor([[ 0.3607, -0.2859, -0.3938],
        [ 0.2429, -1.3833, -2.3134]])
随机数种子: 100
"""

6. 创建全0、全1、全指定值张量

1. torch.zeros(shape)、torch.zeros_like(data) 创建全0张量
# 1. 创建指定形状全0张量
data = torch.zeros(2, 3)
print(data)	# tensor([[0., 0., 0.],
        	#         [0., 0., 0.]])
    
# 2. 根据张量形状创建全0张量
data = torch.randn(3, 3)
data = torch.zeros_like(data)
print(data)	# tensor([[0., 0., 0.],
        	#         [0., 0., 0.],
        	#         [0., 0., 0.]])
2. torch.ones(shape)、torch.ones_like(data) 创建全1张量
# 1. 创建指定形状全1张量
data = torch.ones(2, 3)
print(data)	# tensor([[1., 1., 1.],
       	#		  [1., 1., 1.]])

# 2. 根据张量形状创建全1张量
data = torch.ones_like(data)
print(data)	# tensor([[1., 1., 1.],
       	# 		  [1., 1., 1.]])
3. torch.full(shape,num)、torch.full_like(data,num) 创建全为指定值张量
# 1. 创建指定形状指定值的张量
data = torch.full([2, 3], 10)
print(data)	# tensor([[10, 10, 10],
        	#		  [10, 10, 10]])

# 2. 根据张量形状创建指定值的张量
data = torch.full_like(data, 20)
print(data)	# tensor([[20, 20, 20],
        	#		  [20, 20, 20]])

7. 总结

  • 创建张量的方式
    • torch.tensor() 根据指定数据创建张量
    • torch.Tensor() 根据形状创建张量, 其也可用来创建指定数据的张量
    • torch.IntTensor()、torch.FloatTensor()、torch.DoubleTensor() 创建指定类型的张量
  • 创建线性和随机张量
    • torch.arrange() 和 torch.linspace() 创建线性张量
    • torch.random.initial_seed() 和 torch.random.manual_seed() 随机种子设置
    • torch.randn() 创建随机张量
  • 创建01张量
    • torch.ones() 和 torch.ones_like() 创建全1张量
    • torch.zeros() 和 torch.zeros_like() 创建全0张量
    • torch.full() 和 torch.full_like() 创建全为指定值张量
  • 张量元素类型转换
    • data.type(torch.DoubleTensor)
    • data.double()

2. 张量的元素类型转换

1. tensor对象名.type(torch.TypeTensor) / tensor对象名 = torch.TypeTensor()

data = torch.full([2, 3], 10)
print(data.dtype)						# torch.int64

# 将 data 元素类型转换为 float64 类型
data = data.type(torch.DoubleTensor)
# data = torch.DoubleTensor()
# 转换为其他类型
# data = data.type(torch.ShortTensor)
# data = data.type(torch.IntTensor)
# data = data.type(torch.LongTensor)
# data = data.type(torch.FloatTensor)
print(data.dtype)						# torch.float64

2. tensor对象名.type()

data = torch.full([2, 3], 10)
print(data.dtype)						# torch.int64

# 将 data 元素类型转换为 float64 类型
data = data.double()
# 转换为其他类型
# data = data.short()
# data = data.int()
# data = data.long()
# data = data.float()
print(data.dtype)						# torch.float64

3. 总结

  • 张量元素类型转换

    • data.type(torch.DoubleTensor)

    • data.double()

3. 张量的类型转换

1. 张量 与 ndarray

1. 张量 -> ndarray
1. tensor对象名.numpy():共享内存
# 将张量转换为 numpy 数组
data_tensor = torch.tensor([2, 3, 4])

# 使用张量对象中的 numpy 函数进行转换
data_numpy = data_tensor.numpy()
print(type(data_tensor))                    # <class 'torch.Tensor'>
print(type(data_numpy))                     # <class 'numpy.ndarray'>

# 注意: data_tensor 和 data_numpy 共享内存
# 修改其中的一个,另外一个也会发生改变
# data_tensor[0] = 100
data_numpy[0] = 100
print(data_tensor)                          # tensor([100,   3,   4])
print(data_numpy)                           # [100   3   4]
2. tensor对象名.numpy().copy():不共享内存
# 对象拷贝避免共享内存
data_tensor = torch.tensor([2, 3, 4])

# 使用张量对象中的 numpy 函数进行转换,通过copy方法拷贝对象
data_numpy = data_tensor.numpy().copy()
print(type(data_tensor))                    # <class 'torch.Tensor'>
print(type(data_numpy))                     # <class 'numpy.ndarray'>

# 注意: data_tensor 和 data_numpy 此时不共享内存
# 修改其中的一个,另外一个不会发生改变
# data_tensor[0] = 100
data_numpy[0] = 100
print(data_tensor)                          # tensor([2,   3,   4])
print(data_numpy)                           # [100   3   4]
2. ndarray -> 张量
1. torch.from_numpy(data_np):共享内存
data_numpy = np.array([2, 3, 4])

# 将 numpy 数组转换为张量类型
data_tensor = torch.from_numpy(data_numpy)

# nunpy 和 tensor 共享内存
# data_numpy[0] = 100
data_tensor[0] = 100
print(data_tensor)          # tensor([100,   3,   4], dtype=torch.int32)
print(data_numpy)           # [100   3   4]
2. torch.from_numpy(data_np.copy()):不共享内存
data_numpy = np.array([2, 3, 4])

# 将 numpy 数组转换为张量类型
data_tensor = torch.from_numpy(data_numpy.copy())

# nunpy 和 tensor 共享内存
# data_numpy[0] = 100
data_tensor[0] = 100
print(data_tensor)          # tensor([100,   3,   4], dtype=torch.int32)
print(data_numpy)           # [2 3 4]
3. torch.tensor(data_np):不共享内存
data_numpy = np.array([2, 3, 4])

# 将 numpy 数组转换为张量类型
data_tensor = torch.tensor(data_numpy)

# nunpy 和 tensor 不共享内存
# data_numpy[0] = 100
data_tensor[0] = 100
print(data_tensor)          # tensor([100,   3,   4], dtype=torch.int32)
print(data_numpy)           # [2 3 4]

2. 张量 与 数值

1. data_tensor.item()
# 当张量只包含一个元素时, 可以通过 item() 函数提取出该值
data = torch.tensor([30,])
print(data.item())			# 30
data = torch.tensor(30)
print(data.item())			# 30

3. 总结

  • 张量转换为 numpy 数组

    • data_tensor.numpy()
    • data_tensor.numpy().copy()
  • numpy 转换为张量

    • torch.from_numpy(data_numpy)
    • torch.tensor(data_numpy)
  • 标量张量和数字转换

    • data.item()

4. 张量的数值运算

1. 基本运算(加减乘除取负号绝对值)

"""
加减乘除取负号绝对值:
add、sub、mul、div、neg、abs
add_、sub_、mul_、div_、neg_、abs_(其中带下划线的版本会修改原数据)
"""

data = torch.randint(-5, 10, [2, 3])
print('data:',data)

# 1. 不修改原数据
new_data = data.add(2) # 等价 new_data = data + 10
print('new_data:',new_data)
print('data:',data)

# 2. 直接修改原数据 注意: 带下划线的函数为修改原数据本身
data.add_(2) # 等价 data += 2
print('data:',data)

# 3. 其他函数
print('sub:',data.sub(100))
print('mul:',data.mul(100))
print('div:',data.div(100))
print('neg:',data.neg())
print('abs:',data.abs())

"""
data: tensor([[ 5,  3,  4],
        [ 3,  3, -3]])
        
new_data: tensor([[ 7,  5,  6],
        [ 5,  5, -1]])
        
data: tensor([[ 5,  3,  4],
        [ 3,  3, -3]])
        
data: tensor([[ 7,  5,  6],
        [ 5,  5, -1]])
        
sub: tensor([[ -93,  -95,  -94],
        [ -95,  -95, -101]])
        
mul: tensor([[ 700,  500,  600],
        [ 500,  500, -100]])
        
div: tensor([[ 0.0700,  0.0500,  0.0600],
        [ 0.0500,  0.0500, -0.0100]])
        
neg: tensor([[-7, -5, -6],
        [-5, -5,  1]])
        
abs: tensor([[7, 5, 6],
        [5, 5, 1]])
"""

2. 点乘运算

  • 点乘指(Hadamard)的是 两个 同维矩阵 对应位置 的元素 相乘,使用torch.mul() 或 运算符 * 实现

    data1 = torch.tensor([[1, 2], [3, 4]])
    data2 = torch.tensor([[5, 6], [7, 8]])
    
    # 第一种方式
    data = torch.mul(data1, data2)
    print(data)
    
    # 第二种方式
    data = data1 * data2
    print(data)
    
    """
    tensor([[ 5, 12],
            [21, 32]])
            
    tensor([[ 5, 12],
            [21, 32]])
    """
    

3. 矩阵乘法

  • (n,m)x(m,p) = (n,p)

    • 方式一:运算符 @ 用于进行两个矩阵的乘积运算

      # 点积运算
      data1 = torch.tensor([[1, 2], [3, 4], [5, 6]])
      data2 = torch.tensor([[5, 6], [7, 8]])
      # 方式一:
      data3 = data1 @ data2
      print("data3-->", data3)	# data3--> tensor([[19, 22],
              					#     			   [43, 50],
              					#     			   [67, 78]])
      
    • **方式二:torch.matmul **

      # 点积运算
      data1 = torch.tensor([[1, 2], [3, 4], [5, 6]])
      data2 = torch.tensor([[5, 6], [7, 8]])
      # 方式二:
      data3 = torch.matmul(data1, data2)
      print("data3-->", data3)	# data3--> tensor([[19, 22],
              					#     			   [43, 50],
              					#     			   [67, 78]])
      

4. 总结

  • 张量基本运算函数

    • add、sub、mul、div、neg等函数
    • add_、sub_、mul_、div_、neg_等函数
  • 张量的点乘运算

    • mul 和 运算符*
  • 点积运算

    • 运算符 @ 用于进行两个矩阵的点乘运算

    • torch.matmul 对进行点乘运算的两矩阵形状没有限定,对数输入的 shape 不同的张量, 对应的最后几个维度必须符合矩阵运算规则

5. 张量的运算函数

  • Sum,mean,sqrt,pow,exp,log等
data = torch.randint(0, 10, [2, 3], dtype=torch.float64)
print(data)

# 1. 计算均值
# 注意: tensor 必须为 Float 或者 Double 类型
print('总体mean:',data.mean())
print('各列mean:',data.mean(dim=0)) # 按列计算均值
print('各行mean:',data.mean(dim=1)) # 按行计算均值

# 2. 计算总和
print('总体sum:',data.sum())
print('各列sum:',data.sum(dim=0))
print('各行sum:',data.sum(dim=1))

# 3. 计算平方
print('总体 2 次方:',torch.pow(data,2))

# 4. 计算平方根
print('总体求 平方根:',data.sqrt())

# 5. 指数计算, e^n 次方
print('总体 e^n 次方:',data.exp())

# 6. 对数计算
print('总体求 ln:',data.log())         # 以 e 为底
print('总体求 log2:',data.log2())
print('总体求 lg:',data.log10())

"""
tensor([[8., 9., 4.],
        [5., 7., 2.]], dtype=torch.float64)
        
总体mean: tensor(5.8333, dtype=torch.float64)

各列mean: tensor([6.5000, 8.0000, 3.0000], dtype=torch.float64)

各行mean: tensor([7.0000, 4.6667], dtype=torch.float64)

总体sum: tensor(35., dtype=torch.float64)

各列sum: tensor([13., 16.,  6.], dtype=torch.float64)

各行sum: tensor([21., 14.], dtype=torch.float64)

总体 2 次方: tensor([[64., 81., 16.],
        [25., 49.,  4.]], dtype=torch.float64)
        
总体求 平方根: tensor([[2.8284, 3.0000, 2.0000],
        [2.2361, 2.6458, 1.4142]], dtype=torch.float64)
        
总体 e^n 次方: tensor([[2.9810e+03, 8.1031e+03, 5.4598e+01],
        [1.4841e+02, 1.0966e+03, 7.3891e+00]], dtype=torch.float64)
        
总体求 ln: tensor([[2.0794, 2.1972, 1.3863],
        [1.6094, 1.9459, 0.6931]], dtype=torch.float64)
        
总体求 log2: tensor([[3.0000, 3.1699, 2.0000],
        [2.3219, 2.8074, 1.0000]], dtype=torch.float64)
        
总体求 lg: tensor([[0.9031, 0.9542, 0.6021],
        [0.6990, 0.8451, 0.3010]], dtype=torch.float64)
"""

6. 张量的索引操作

# 随机生成数据
data = torch.randint(0, 10, [4, 5])
print(data)

"""
tensor([[3, 0, 1, 3, 1],
        [9, 3, 0, 6, 4],
        [9, 6, 0, 0, 7],
        [4, 7, 1, 0, 1]])
"""

1. 简单行、列索引

print(data[0])      # tensor([3, 0, 1, 3, 1])
print(data[:, 0])   # tensor([3, 9, 9, 4])

2. 列表索引

# 返回 (0, 1)、(1, 2) 两个位置的元素
print(data[[0, 1], [1, 2]])     # tensor([0, 0])

# 返回 0、1 行的 1、2 列共4个元素
print(data[[[0], [1]], [1, 2]]) # tensor([[0, 1],
                                #         [3, 0]])

3. 范围索引

# 前3行的前2列数据
print(data[:3, :2])		# tensor([[3, 0],
        				# 		  [9, 3],
        				# 		  [9, 6]])

# 第2行到最后的前2列数据
print(data[2:, :2])		# tensor([[9, 6],
        				# 		  [4, 7]])

4. 布尔索引

# 第三列大于5的行数据
print(data[data[:, 2] > 5])     # tensor([], size=(0, 5), dtype=torch.int64)

# 第二行大于5的列数据
print(data[:, data[1] > 5])     #tensor([[3, 3],
                                #        [9, 6],
                                #        [9, 0],
                                #        [4, 0]]) 

5. 多维索引

data = torch.randint(0, 10, [3, 4, 5])
print(data)
# 获取0轴上的第一个数据
print(data[0, :, :])
# 获取1轴上的第一个数据
print(data[:, 0, :])
# 获取2轴上的第一个数据
print(data[:, :, 0])

"""
tensor([[[9, 2, 0, 1, 8],
         [9, 1, 3, 3, 2],
         [8, 9, 1, 5, 1],
         [3, 5, 6, 1, 3]],

        [[3, 9, 9, 4, 9],
         [6, 1, 7, 1, 7],
         [0, 9, 8, 2, 7],
         [4, 8, 1, 7, 1]],

        [[3, 2, 4, 4, 2],
         [3, 2, 5, 1, 2],
         [8, 7, 6, 2, 4],
         [3, 8, 5, 8, 0]]])
         
tensor([[9, 2, 0, 1, 8],
        [9, 1, 3, 3, 2],
        [8, 9, 1, 5, 1],
        [3, 5, 6, 1, 3]])
        
tensor([[9, 2, 0, 1, 8],
        [3, 9, 9, 4, 9],
        [3, 2, 4, 4, 2]])
        
tensor([[9, 9, 8, 3],
        [3, 6, 0, 4],
        [3, 3, 8, 3]])
"""

7. 张量的形状操作

1. 使用 shape 属性或者 size 方法都可以获得张量的形状

data = torch.tensor([[10, 20, 30], [40, 50, 60]])

print(data.shape, data.shape[0], data.shape[1])	# torch.Size([2, 3]) 2 3

print(data.size(), data.size(0), data.size(1))	# torch.Size([2, 3]) 2 3

2. 使用 reshape 函数修改张量形状

new_data = data.reshape(1, 6)
print(new_data.shape)			# torch.Size([1, 6])
print(new_data)					# tensor([[10, 20, 30, 40, 50, 60]])

new_data2 = data.reshape(-1)
print(new_data2.shape)			# torch.Size([6])
print(new_data2)				# tensor([10, 20, 30, 40, 50, 60])

3. squeeze() 和 unsqueeze() 函数

# squeeze 函数删除形状为 1 的维度(降维),unsqueeze 函数添加形状为1的维度(升维)。

mydata1 = torch.tensor([1, 2, 3, 4, 5]) 
print('mydata1--->', mydata1.shape, mydata1) # 一个普通的数组 1维数据
mydata2 = mydata1.unsqueeze(dim=0)
print('在0位置上 拓展维度:', mydata2, mydata2.shape) # 1*5
mydata3 = mydata1.unsqueeze(dim=1)
print('在1位置上 拓展维度:', mydata3, mydata3.shape) # 5*1
mydata4 = mydata1.unsqueeze(dim=-1)
print('在-1位置上 拓展维度:', mydata4, mydata4.shape) # 5*1
mydata5 = mydata4.squeeze()
print('压缩维度(删除形状为1的维度):', mydata5, mydata5.shape) # 5

"""
mydata1---> torch.Size([5]) tensor([1, 2, 3, 4, 5])
在0位置上 拓展维度: tensor([[1, 2, 3, 4, 5]]) torch.Size([1, 5])
在1位置上 拓展维度: tensor([[1],
        				  [2],
        				  [3],
        				  [4],
        				  [5]]) torch.Size([5, 1])
在-1位置上 拓展维度: tensor([[1],
        				   [2],
        				   [3],
        				   [4],
        				   [5]]) torch.Size([5, 1])
压缩维度(删除形状为1的维度): tensor([1, 2, 3, 4, 5]) torch.Size([5])
"""

4. transpose() 和 permute()函数

# transpose 函数可以实现交换张量形状的指定维度
# 例如: 一个张量的形状为 (2, 3, 4) 可以通过 transpose 函数把 3 和 4 进行交换, 将张量的形状变为 (2, 4, 3) 
# permute 函数可以一次交换更多的维度

data = torch.tensor(np.random.randint(0, 10, [3, 4, 5]))
print('data shape:', data.size())				# data shape: torch.Size([3, 4, 5])
# 1 交换位置1和2维度
mydata2 = torch.transpose(data, 1, 2)
print('mydata2.shape--->', mydata2.shape)		# mydata2.shape---> torch.Size([3, 5, 4])

# 2 将data 的形状修改为 (4, 5, 3), 需要变换多次
mydata3 = torch.transpose(data, 0, 1)
mydata4 = torch.transpose(mydata3, 1, 2)
print('mydata4.shape--->', mydata4.shape)		# mydata4.shape---> torch.Size([4, 5, 3])

# 3 使用 permute 函数将形状修改为 (4, 5, 3)
# 3-1 方法1
mydata5 = torch.permute(data, [1, 2, 0])
print('mydata5.shape--->', mydata5.shape)		# mydata5.shape---> torch.Size([4, 5, 3])

# 3-2 方法2
mydata6 = data.permute([1, 2, 0])
print('mydata6.shape--->', mydata6.shape)		# mydata6.shape---> torch.Size([4, 5, 3])

5. view() 和 contiguous()函数

"""
view 函数也可以用于修改张量的形状,但只能用于存储在整块内存中的张量。
在 PyTorch 中,有些张量是由不同的数据块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理
例如: 一个张量经过了 transpose 或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作
若要使用view函数, 需要使用 contiguous() 变成连续以后再使用 view 函数

contiguous():将张量转换为整块内存的张量
is_contiguous():判断张量是否使用整块内存
"""

data = torch.tensor( [[10, 20, 30],[40, 50, 60]])
print('data--->', data, data.shape)	# data---> tensor([[10, 20, 30],[40, 50, 60]]) torch.Size([2, 3])

# 1 判断是否使用整块内存
print(data.is_contiguous()) # True

# 2 view
mydata2 = data.view(3, 2)
print('mydata2--->', mydata2, mydata2.shape)					# torch.Size([3, 2])

# 3 判断是否使用整块
print('mydata2.is_contiguous()--->', mydata2.is_contiguous())   # True

# 4 使用 transpose 函数修改形状
mydata3 = torch.transpose(data, 0, 1) 
print('mydata3--->', mydata3, mydata3.shape) 					# torch.Size([3, 2])
print('mydata3.is_contiguous()--->', mydata3.is_contiguous())   # False

# 5 需要先使用 contiguous 函数转换为整块内存的张量,再使用 view 函数
print (mydata3.contiguous().is_contiguous())                    # True
mydata4 = mydata3.contiguous().view(2, 3)
print('mydata4--->', mydata4.shape, mydata4)					# torch.Size([2, 3])

6. 总结

  1. reshape 函数可以在保证张量数据不变的前提下改变数据的维度
  2. squeeze 和 unsqueeze 函数可以用来增加或者减少维度
  3. transpose 函数可以实现交换张量形状的指定维度, permute 可以一次交换更多的维度
  4. view 函数也可以用于修改张量的形状, 但是它要求被转换的张量内存必须连续,所以一般配合 contiguous 函数使用

8. 张量的拼接操作

1. torch.cat():两个张量根据指定的维度拼接起来,不改变其余维度数

# 注意:拼接时,除要操作的维度外,其它维度要保持一致
data1 = torch.randint(0, 10, [1, 2, 3])
data2 = torch.randint(0, 10, [1, 2, 3])
print('data1:',data1)
print('data2:',data2)

# 1. 按0维度拼接
new_data = torch.cat([data1, data2], dim=0)
print('new_data:',new_data)
print('new_data.shape:',new_data.shape)

# 2. 按1维度拼接
new_data = torch.cat([data1, data2], dim=1)
print('new_data:',new_data)
print('new_data.shape:',new_data.shape)

# 3. 按2维度拼接
new_data = torch.cat([data1, data2], dim=2)
print('new_data:',new_data)
print('new_data.shape:',new_data.shape)

"""
data1: tensor([[[2, 9, 5],
         [8, 0, 9]]])
         
data2: tensor([[[3, 4, 2],
         [2, 0, 8]]])
         
new_data: tensor([[[2, 9, 5],
         [8, 0, 9]],

        [[3, 4, 2],
         [2, 0, 8]]])
         
new_data.shape: torch.Size([2, 2, 3])

new_data: tensor([[[2, 9, 5],
         [8, 0, 9],
         [3, 4, 2],
         [2, 0, 8]]])
         
new_data.shape: torch.Size([1, 4, 3])

new_data: tensor([[[2, 9, 5, 3, 4, 2],
         [8, 0, 9, 2, 0, 8]]])
         
new_data.shape: torch.Size([1, 2, 6])
"""

9. 自动微分模块

1. 概念

​ 训练神经网络时,最常用的算法就是 反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应
参数的梯度进行调整。

​ 为了计算这些梯度,PyTorch内置了名为 torch.autograd 的微分引擎。它支持任意计算图的自动梯度计算
请添加图片描述

2. 例子

1. 当 x 为标量时梯度的计算
import torch

def test01():
    # 数据:特征 + 目标值
    # 特征
    x = torch.tensor(5)
    # 目标值
    y = torch.tensor(0.)
    
    # 设置 要更新的权重 和 偏置的初始值
    # 要对谁求梯度:就要把 requires_grad 设置为 True
    # 权重
    w = torch.tensor(1., requires_grad=True, dtype=torch.float32)
    # 偏置
    b = torch.tensor(3., requires_grad=True, dtype=torch.float32)
    
    # 设置网络的输出值
    z = x * w + b       # 矩阵点乘
    
    # 设置损失函数,并进行损失的计算
    # (预测值, 真实值)
    loss = torch.nn.MSELoss()
    loss = loss(z, y)
    
    # 自动微分
    loss.backward()
    print(loss.item())  # 损失值
    
    # 打印 w,b 变量的梯度
    # backward 函数计算的梯度值会存储在张量的 grad 变量中
    print("w的梯度:", w.grad)
    print("b的梯度", b.grad)
    
    # 使用随机梯度下降(SGD)更新参数
    learning_rate = 0.01
    
    # 更新权重和偏置
    with torch.no_grad():
        w -= learning_rate * w.grad
        b -= learning_rate * b.grad
    
    # 打印更新后的权重和偏置值
    print("更新后的权重:", w)
    print("更新后的偏置:", b)

if __name__ == '__main__':
    test01()
    
"""
64.0
w的梯度: tensor(80.)
b的梯度 tensor(16.)
更新后的权重: tensor(0.2000, requires_grad=True)
更新后的偏置: tensor(2.8400, requires_grad=True)
"""
2. 当 x 有多个维度时梯度的计算
import torch

def test02():
    # 输入张量 2*5
    x = torch.ones(2,5)
    # 目标值是 2*3
    y = torch.zeros(2,3)
    
    # 设置 要更新的权重 和 偏置的初始值
    w = torch.randn(5, 3,requires_grad=True)
    b = torch.randn(3, requires_grad=True)

    # 设置 网络的输出值
    z = torch.matmul(x, w) + b  # 矩阵乘法 (2 * 5 @ 5 * 3 + b)
    print(z.shape)
    
    # 设置损失函数,并进行损失的计算
    loss = torch.nn.MSELoss()
    loss = loss(z, y)
    print(loss.item())
    
    # 自动微分
    loss.backward()
    
    # 打印 w,b 变量的梯度
    # backward 函数计算的梯度值会存储在张量的 grad 变量中
    print("w的梯度:", w.grad)
    print("b的梯度:", b.grad)
    
if __name__ == '__main__':
    test02()
    
"""
torch.Size([2, 3])
1.0808545351028442
w的梯度: tensor([[0.5029, 0.6720, 0.8583],
        [0.5029, 0.6720, 0.8583],
        [0.5029, 0.6720, 0.8583],
        [0.5029, 0.6720, 0.8583],
        [0.5029, 0.6720, 0.8583]])
b的梯度: tensor([0.5029, 0.6720, 0.8583])
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值