实验2:Pytorch-Tensor基础

使用pytorch实现张量的运算

张量:通俗来讲就是一个多维数组。

一、创建张量

学习了三种创建张量的方式【※张量在任何一个维度上的元素数量必须相等】

(1)指定数据

#========create torch-指定数据创建=========================
# 创建一维张量
ndim_1_Tensor = torch.tensor([2.0,3.0,4.0])
print(ndim_1_Tensor)
# 创建二维Tensor
ndim_2_Tensor = torch.tensor([[1.0, 2.0, 3.0],
                                  [4.0, 5.0, 6.0]])
print(ndim_2_Tensor)
# 创建多维Tensor
ndim_3_Tensor = torch.tensor([[[1, 2, 3, 4, 5],
                                   [6, 7, 8, 9, 10]],
                                  [[11, 12, 13, 14, 15],
                                   [16, 17, 18, 19, 20]]])
print(ndim_3_Tensor)

 (2)指定形状

#========create torch-指定形状创建===================================
m,n=2,3
# 使用torch.zeros创建数据全为0,形状为[m, n]的Tensor
zeros_Tensor = torch.zeros([m,n])
# 使用torch.ones创建数据全为1,形状为[m, n]的Tensor
ones_Tensor = torch.ones([m,n])
# 使用torch.full创建数据全为指定值,形状为[m, n]的Tensor,这里我们指定数据为10
full_Tensor = torch.full([m,n],10)
print("zeros_Tensor:",zeros_Tensor)
print("ones_Tensor:",ones_Tensor)
print("full_Tensor:",full_Tensor)

(3)指定区间

#========create torch-指定区间创建=====================================
# 使用torch.arange创建以步长step均匀分隔数值区间[start, end)的一维Tensor
arange_Tensor = torch.arange(start=1, end=5, step=1)
# 使用torch.linspace创建以元素个数num均匀分隔数值区间[start, end]的Tensor
linspace_Tensor = torch.linspace(start=1, end=5, steps=9)

print('arange Tensor: ', arange_Tensor)
print('linspace Tensor: ', linspace_Tensor)

【总结】

  • 有几组[ ]就是几维张量
  •  指定形状时[ ]中有几个数字就是几维。
  • 指定数据常用函数torch.tensor( );指定形状常用函数torch.zeros( )  、torch.ones( )、torch.full( );指定区间常用函数torch.arrange( start,end,step)、torch.linspace( )、torch.rand( )、torch.randint() 。

 二、张量的属性

学习了张量的形状属性、数据类型、设备位置三个重要属性。

(1)形状属性

import torch

# 创建一个 4 维张量,其中第一个维度有2个元素,第二个维度有3个元素,第三个维度有4个元素,第四个维度有5个元素
ndim_4_Tensor = torch.ones([2, 3, 4, 5])

# 打印张量的维度数量(即张量的阶数,这里是4维)
print("Number of dimensions:", ndim_4_Tensor.ndim)

# 打印张量的形状(即每个维度上的元素个数,这里是[2, 3, 4, 5])
print("Shape of Tensor:", ndim_4_Tensor.shape)

# 打印张量第一个维度的元素个数(这里是2)
print("Elements number along axis 0 of Tensor:", ndim_4_Tensor.shape[0])

# 打印张量最后一个维度的元素个数(这里是5)
print("Elements number along the last axis of Tensor:", ndim_4_Tensor.shape[-1])

# 打印张量的总元素个数(即所有维度的元素总和,这里是 2*3*4*5 = 120)
print('Number of elements in Tensor: ', ndim_4_Tensor.size())

改变张量的形状:torch.reshape()、torch.view( )

# 定义一个shape为[3,2,5]的三维Tensor
ndim_3_Tensor = torch.tensor([[[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, 30]]])
print("the shape of ndim_3_Tensor:", ndim_3_Tensor.shape)

# torch.reshape 可以保持在输入数据不变的情况下,改变数据形状。这里我们设置reshape为[2,5,3]
reshape_Tensor = torch.reshape(ndim_3_Tensor, [2, 5, 3])
print("After reshape:\n", reshape_Tensor)

#==========================改变形状属性->view====================
# 使用 view() 改变张量形状,将3维张量转为1维
# view([-1]) 中的 -1 表示自动推断这个维度上的元素个数
new_Tensor1_pytorch = ndim_3_Tensor.view([-1])
print('new Tensor 1 shape: ', new_Tensor1_pytorch.shape)
# 打印新的1维张量的形状

# 使用 view() 改变张量形状,将原来的3维张量转换为 [3, 5, 2] 形状
# 要求新的形状的元素总数与原张量的元素总数相等,否则会报错
new_Tensor2_pytorch = ndim_3_Tensor.view([3, 5, 2])
print('new Tensor 2 shape: ', new_Tensor2_pytorch.shape)
# 打印新的3维张量的形状
#==========================改变形状属性->view====================
# 使用 view() 改变张量形状,将3维张量转为1维
# view([-1]) 中的 -1 表示自动推断这个维度上的元素个数
new_Tensor1_pytorch = ndim_3_Tensor.view([-1])
print('new Tensor 1 shape: ', new_Tensor1_pytorch.shape)
# 打印新的1维张量的形状

# 使用 view() 改变张量形状,将原来的3维张量转换为 [3, 5, 2] 形状
# 要求新的形状的元素总数与原张量的元素总数相等,否则会报错
new_Tensor2_pytorch = ndim_3_Tensor.view([3, 5, 2])
print('new Tensor 2 shape: ', new_Tensor2_pytorch.shape)
# 打印新的3维张量的形状

                       

(2)数据类型 

# 使用torch.tensor通过已知数据来创建一个Tensor
print("Tensor dtype from Python integers:", torch.tensor(1).dtype)
print("Tensor dtype from Python floating point:", torch.tensor(1.0).dtype)

                                 

改变张量的数据类型

#=============================改变张量的数据类型
# 定义dtype为float32的Tensor
float32_Tensor = torch.tensor(1.0)
# Tensor.type可以将输入数据的数据类型转换为指定的dtype并输出。支持输出和输入数据类型相同。
#int64_Tensor = float32_Tensor.type(torch.int64)
int64_Tensor = float32_Tensor.to(torch.int64)
print("Tensor after type to int64:", int64_Tensor.dtype)

                                              

(3)张量的设备位置:如何查看设备位置?如何创建GPU上的张量?

#===========张量的设备位置=========
# 创建CPU上的PyTorch Tensor
cpu_Tensor = torch.tensor(1)
# 通过Tensor.device查看张量所在设备位置
print('CPU Tensor: ', cpu_Tensor.device)

# 创建GPU上的PyTorch Tensor
if torch.cuda.is_available():
    gpu_Tensor = torch.tensor([2,3,4,5], device=torch.device('cuda:0'))#指定了设备,cuda:0表示第一个GPU
    # gpu_Tensor = torch.tensor([2,3,4,5], device='cuda')# 允许PyTorch自动选择一个可用的CUDA设备
    print('GPU Tensor: ', gpu_Tensor.device)
else:
    print('GPU is not available.')

                                                

 三、张量与Numpy数组的转换

torch.from_numpy():用于将 NumPy 数组转换为 PyTorch 张量。

  tensor.numpy():用于将 PyTorch 张量转换为 NumPy 数组。

#===============numpy数组与torch的==============
ndim_1_Tensor = torch.tensor([1., 2.])
# 将当前 Tensor 转化为 numpy.ndarray
print('Tensor to numpy: ', ndim_1_Tensor.numpy())

                                      

共享内存:转换后,张量和数组共享内存,修改一个会影响另一个。

【如果 PyTorch 张量在 GPU 上,必须先将其转移到 CPU 上再进行转换,否则会报错】

四、张量的访问

通过索引/切片

#========================通过索引/切片访问张量========
# 定义1个一维Tensor
ndim_1_Tensor = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])

print("原型张量:", ndim_1_Tensor)
print("第一个元素:", ndim_1_Tensor[0])
print("最后一个元素:", ndim_1_Tensor[-1])
print("所有元素:", ndim_1_Tensor[:])
print("前3个元素:", ndim_1_Tensor[:3])
print("步长为3:", ndim_1_Tensor[::3])
# print("Reverse:", ndim_1_Tensor[::-1])->Paddle支持使用Tensor[::-1]的方式进行Reverse,Pytorch不支持此功能。

                                 

五、张量的修改

#=======================张量的修改====================
# 定义1个二维Tensor
ndim_2_Tensor = torch.ones([2, 3], dtype=torch.float32)
print('原始张量: ', ndim_2_Tensor)
ndim_2_Tensor[0] = 0
print('修改第一维为0: ', ndim_2_Tensor)
ndim_2_Tensor[0:1] = 2.1
print('修改第1维为2.1: ', ndim_2_Tensor)
ndim_2_Tensor[...] = 3
print('修改全部Tensor: ', ndim_2_Tensor)

                                      

六、张量的数学运算

以加法为例,有如下两种实现方式:

1)torch.add(x,y)。 2)类成员函数x.add(y)。3)直接相加

#=================张量的运算==============
# 定义两个Tensor
x = torch.tensor([[1.1, 2.2], [3.3, 4.4]], dtype=torch.float64)
y = torch.tensor([[5.5, 6.6], [7.7, 8.8]], dtype=torch.float64)
# 第一种调用方法,paddle.add逐元素相加算子,并将各个位置的输出元素保存到返回结果中
print('Method 1: ', torch.add(x, y))
# 第二种调用方法
print('Method 2: ', x.add(y))

                        

其他

# 张量的数学运算
x = torch.tensor([1,2,3,4,5])
y = torch.tensor([-1,-2,-3,-4,-5])
print("x:",x)
print("y:",y)
print("y.abs():",y.abs())
print("x.exp():",x.exp())
print("x.log():",x.log())
print("x.reciprocal():",x.reciprocal())
print("x.square():",x.square())
print("x.sqrt():",x.sqrt())
print("x.sin():",x.sin())
print("x.cos():",x.cos())
print("x.subtract(y):",x.subtract(y))
print("x.divide(y):",x.divide(y))
print("x.pow(y):",x.pow(y))
print("x.max():",x.max())
print("x.min():",x.min())
print("x.prod():",x.prod())
print("x.sum():",x.sum())

                

七、张量的逻辑运算

张量的逻辑运算包括各种布尔运算,如逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)以及比较运算

#=============# 张量的逻辑运算===========
x = torch.tensor([1,2,3,4,5])
y = torch.tensor([1,3,3,4,4])
print("x:",x)
print("y:",y)
print("x.isfinite():",x.isfinite())
print("x.equal(y):",x.equal(y))
print("x.not_equal(y):",x.not_equal(y))
print("x.less_equal(y):",x.less_equal(y))
print("x.greater_equal(y):",x.greater_equal(y))
print("x.allclose(y):",x.allclose(y))

                

  • x.isfinite(): 检查每个元素是否为有限数值。
  • x.equal(y): 检查两个张量是否完全相同。
  • x.not_equal(y): 检查每对元素是否不相等。
  • x.less_equal(y): 检查每对元素是否小于或等于。
  • x.greater_equal(y): 检查每对元素是否大于或等于。
  • x.allclose(y): 检查两个张量是否在指定的相对误差范围内接近相等。

 八、张量的矩阵运算

import torch

# 创建两个张量 x 和 y,数据类型为浮点数
x = torch.tensor([[1, 2, 3],
                  [4, 5, 6]], dtype=torch.float32)
y = torch.tensor([[1, 1, 1],
                  [2, 2, 2]], dtype=torch.float32)

print("x:", x)  # 输出张量 x 的值
print("y:", y)  # 输出张量 y 的值

# 对张量 x 进行转置操作
print("x.t():", x.t())  # 输出:tensor([[1., 4.], [2., 5.], [3., 6.]])
# `x.t()` 返回张量 x 的转置,即交换行和列。

# 计算张量 x 的 Frobenius 范数
print("x.norm('fro'):", x.norm('fro'))  # 输出:tensor(9.5394)
# `x.norm('fro')` 计算 Frobenius 范数,是矩阵元素的平方和的平方根,也就是 `sqrt(sum(x^2))`。

# 计算张量 x 和 y 之间的 L2 距离
print("x.dist(y, p=2):", x.dist(y, p=2))  # 输出:tensor(6.5574)
# `x.dist(y, p=2)` 计算两个张量 x 和 y 之间的 L2 距离,即 `sqrt(sum((x - y)^2))`。

# 矩阵乘法,y.t() 是 y 的转置
print("x.matmul(y):", x.matmul(y.t()))  # 输出:tensor([[  6.,  12.], [ 15.,  33.]])
# `x.matmul(y.t())` 计算矩阵 x 和 y 的转置的矩阵乘法,即 `x * y.t()`。

                                 

九、张量的广播机制

#===============广播机制======================
# 当两个Tensor的形状一致时,可以广播
x = torch.ones((2, 3, 4))
y = torch.ones((2, 3, 4))
z = x + y
print('两个形状一样的张量广播 ', z.shape)

x = torch.ones((2, 3, 1, 5))
y = torch.ones((3, 4, 1))
# 从后往前依次比较:
# 第一次:y的维度大小是1
# 第二次:x的维度大小是1
# 第三次:x和y的维度大小相等,都为3
# 第四次:y的维度不存在
# 所以x和y是可以广播的
z = x + y
print('两个形状不一样的张量广播:', z.shape)

                         

torch.matmul 广播规则

  1. 一维张量的点积

    如果两个张量都是一维的,torch.matmul 将计算它们的点积(内积)

    import torch
    
    x = torch.tensor([1, 2, 3])  # 一维张量
    y = torch.tensor([4, 5, 6])  # 一维张量
    result = torch.matmul(x, y)
    print(result)  # 输出:32 (即 1*4 + 2*5 + 3*6)
    
  2. 二维张量的矩阵乘法

    如果两个张量都是二维的,torch.matmul 将执行矩阵乘法(即矩阵与矩阵的乘积)。

    x = torch.tensor([[1, 2], [3, 4]])  # 2x2 矩阵
    y = torch.tensor([[5, 6], [7, 8]])  # 2x2 矩阵
    result = torch.matmul(x, y)
    print(result)
    # 输出:
    # tensor([[19, 22],
    #         [43, 50]])
    

  3. 一维张量与二维张量的乘法

    如果第一个张量是一维的,第二个张量是二维的,则 torch.matmul 会将一维张量视为行向量,并将其与二维张量相乘。结果会是二维张量。最终会删除一维张量的前置维度。

    x = torch.tensor([1, 2, 3])  # 1x3 行向量
    y = torch.tensor([[4, 5], [6, 7], [8, 9]])  # 3x2 矩阵
    result = torch.matmul(x, y)
    print(result)
    # 输出:
    # tensor([40, 46])
    

  4. 二维张量与一维张量的乘法

    如果第一个张量是二维的,第二个张量是一维的,则 torch.matmul 会将一维张量视为列向量,并将其与二维张量相乘。结果会是二维张量。

    x = torch.tensor([[1, 2], [3, 4]])  # 2x2 矩阵
    y = torch.tensor([5, 6])  # 2x1 列向量
    result = torch.matmul(x, y)
    print(result)
    # 输出:
    # tensor([17, 39])
    
  5. N维张量的矩阵乘法(N > 2)

    对于N维张量(N > 2),torch.matmul 会根据广播规则扩展非矩阵维度(除最后两个维度外其余维度)。具体来说,广播规则会将较小的张量广播到与较大的张量的前面维度对齐,然后执行最后两个维度上的矩阵乘法。

    x = torch.tensor([[[[1, 2]], [[3, 4]]], [[[5, 6]], [[7, 8]]]])  # 2x2x1x2 张量
    y = torch.tensor([[[[1, 0]], [[0, 1]]], [[[1, 1]], [[0, 0]]]])  # 2x2x2x2 张量
    
    # x的形状为 [2, 2, 1, 2]
    # y的形状为 [2, 2, 2, 2]
    # 执行广播后的形状是 [2, 2, 2, 2]
    result = torch.matmul(x, y)
    print(result)
    # 输出:
    # tensor([[[[ 1,  2],
    #          [ 3,  4]],
    #         [[ 2,  4],
    #          [ 8, 12]]],
    #
    #        [[[ 5,  6],
    #          [ 7,  8]],
    #         [[ 6,  8],
    #          [14, 16]]]])
    

    算子

     算子(Operator)在深度学习中是指在计算图中执行特定操作的基本单元。(我理解为底层打包好的函数)

pytorch框架的几个常用算子:

卷积

  • 二维卷积: torch.nn.Conv2d(in_channels, out_channels, kernel_size)

池化

  • 最大池化: torch.nn.MaxPool2d(kernel_size)
  • 平均池化: torch.nn.AvgPool2d(kernel_size)

归一化

  • 批量归一化: torch.nn.BatchNorm2d(num_features)

激活函数

  • ReLU: torch.relu(x)
  • Sigmoid: torch.sigmoid(x)
  • Tanh: torch.tanh(x)

数据预处理 

(1)对house_tiny.csv'进行缺失值处理并转为张量形式

import pandas as pd
import numpy as np
import torch

# 读取CSV文件
data = pd.read_csv('house_tiny.csv')
print("原始数据\n", data)

# ====== 处理缺失值
# 只对数值列填充缺失值为均值
numeric_cols = data.select_dtypes(include=[np.number]).columns
data[numeric_cols] = data[numeric_cols].fillna(value=data[numeric_cols].mean())

# 对于非数值列(如字符串),填充为 'Unknown'
non_numeric_cols = data.select_dtypes(exclude=[np.number]).columns
data[non_numeric_cols] = data[non_numeric_cols].fillna(value='Unknown')

print("处理缺失值后\n", data)

# ======== 处理布尔值,将 True/False 转换为 1/0
data = data.applymap(lambda x: 1 if x is True else (0 if x is False else x))

# ======== 处理离散值
# 使用 get_dummies 对离散值进行独热编码
data_encoded = pd.get_dummies(data)
# 替换掉 True/False,确保所有布尔类型都转为 0/1
data_encoded = data_encoded.replace({True: 1, False: 0})  # 重新赋值给 data_encoded
print("处理离散值后\n", data_encoded)

# ======== 转换为张量形式
data_array = np.array(data_encoded)  # 转换为 NumPy 数组
data_tensor = torch.tensor(data_array)  # 转换为张量,指定类型为 float32
print("转换为张量后\n", data_tensor)

                     

(2)对boston_house_prices.csv数据集进行缺失值处理并转化为张量形式

data = pd.read_csv('boston_house_prices.csv')
print("数据集展示\n",data)
# 检查DataFrame中的缺失值
# missing_values = data.isna()  # 或者 df.isnull()
missing_count = data.isna().sum()  # 或者 df.isnull().sum()
print("缺失值数量统计\n",missing_count)
# 转换为张量形式
data = np.array(data)
data = torch.tensor(data)
print("转换为张量形式\n",data)

        

(3)对iris.csv数据集进行缺失值处理并转化为张量形式

data = pd.read_csv('Iris.csv')
print("数据集展示\n",data)

# 检查DataFrame中的缺失值
# missing_values = data.isna()  # 或者 df.isnull()
missing_count = data.isna().sum()  # 或者 df.isnull().sum()
print("缺失值数量统计\n",missing_count)

data['Species'], _ = pd.factorize(data['Species'])
# 转换为张量形式
data = np.array(data)
data = torch.tensor(data)
print("转换为张量形式\n",data)

           

          

实验心得

Tensor相对于Numpy来说难度略微提高。本实验分为了三块来学习:

第一部分了解张量的概念、与numpy之间的不同、属性以及基本的tensor处理数据的函数(好多好多,还是需要不断使用才能加深记忆);

第二部分主要了解算子的概念(类似函数);

第三部分掌握了对数据集的一些处理操作(缺失值处理、离散化、转换为张量)

实验过程中我遇到了以下问题并成功解决:

  1. 由于离散化时候用get_demmies对离散值进行独热编码,但不知为什么输出编码0对应false,1对应true,造成转化张量时将其当成字符串无法转换。解决方法# 替换掉 True/False,确保所有布尔类型都转为 0/1

data_encoded = data_encoded.replace({True: 1, False: 0})

这里注意转换张量形式前要先使用np.array()转化为Numpy数组再使用torch.tensor()函数转化为张量形式。

    2. 处理house_tiny.csv数据集时,对于缺失值的处理一开始我没有对数值列和非数值列分别处理,导致报错,后面分别对其分别处理就好了。

(翻到老师的博客,里面有很多学习资料,记录在这里~~~)

https://blog.csdn.net/qq_38975453/article/details/126491559icon-default.png?t=O83Ahttps://blog.csdn.net/qq_38975453/article/details/126491559​​​​​​​

                              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值