DAY48

随机张量的生成
在 PyTorch 中,torch.randn()是一个常用的随机张量生成函数,它可以创建一个由标准正态分布(均值为 0,标准差为 1)随机数填充的张量。这种随机张量在深度学习中非常实用,常用于初始化模型参数、生成测试数据或模拟输入特征。

torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

- size:必选参数,表示输出张量的形状(如(3, 4)表示 3 行 4 列的矩阵)。

- dtype:可选参数,指定张量的数据类型(如torch.float32、torch.int64等)。

- device:可选参数,指定张量存储的设备(如'cpu'或'cuda')。

- requires_grad:可选参数,是否需要计算梯度(常用于训练模型时)。

import torch
# 生成标量(0维张量)
scalar = torch.randn(())
print(f"标量: {scalar}, 形状: {scalar.shape}")  

orch.rand():生成在 [0, 1) 范围内均匀分布的随机数。

torch.randint():生成指定范围内的随机整数

torch.normal():生成指定均值和标准差的正态分布随机数。

广播机制
PyTorch 的广播机制(Broadcasting)是一种高效的张量运算特性,允许在不同形状的张量之间执行元素级操作(如加法、乘法),而无需显式扩展或复制数据。这种机制通过自动调整张量维度来实现形状兼容,使代码更简洁、计算更高效。

当对两个形状不同的张量进行运算时,PyTorch 会按以下规则自动处理维度兼容性:

1. 从右向左比较维度:PyTorch 从张量的最后一个维度(最右侧)开始向前逐维比较。

2. 维度扩展条件:

   - 相等维度:若两个张量在某一维度上大小相同,则继续比较下一维度。

   - 一维扩展:若其中一个张量在某一维度上大小为 1,则该维度会被扩展为另一个张量对应维度的大小。

  - 不兼容错误:若某一维度大小既不相同也不为 1,则抛出 `RuntimeError`。-----维度必须满足广播规则,否则会报错。

3. 维度补全规则:若一个张量的维度少于另一个,则在其**左侧补 1** 直至维度数匹配。

加法的广播机制

二维张量与一维向量相加

import torch
 
# 创建原始张量
a = torch.tensor([[10], [20], [30]])  # 形状: (3, 1)
b = torch.tensor([1, 2, 3])          # 形状: (3,)
 
result = a + b
# 广播过程
# 1. b补全维度: (3,) → (1, 3)
# 2. a扩展列: (3, 1) → (3, 3)
# 3. b扩展行: (1, 3) → (3, 3)
# 最终形状: (3, 3)

三维张量与二维张量相加

# 创建原始张量
a = torch.tensor([[[1], [2]], [[3], [4]]])  # 形状: (2, 2, 1)
b = torch.tensor([[10, 20]])               # 形状: (1, 2)
 
# 广播过程
# 1. b补全维度: (1, 2) → (1, 1, 2)
# 2. a扩展第三维: (2, 2, 1) → (2, 2, 2)
# 3. b扩展第一维: (1, 1, 2) → (2, 1, 2)
# 4. b扩展第二维: (2, 1, 2) → (2, 2, 2)
# 最终形状: (2, 2, 2)

乘法的广播机制

矩阵乘法(@)的特殊规则

矩阵乘法除了遵循通用广播规则外,还需要满足矩阵乘法的维度约束:

最后两个维度必须满足:A.shape[-1] == B.shape[-2](即 A 的列数等于 B 的行数)

其他维度(批量维度):遵循通用广播规则

import torch
 
# A: 批量大小为2,每个是3×4的矩阵
A = torch.randn(2, 3, 4)  # 形状: (2, 3, 4)
 
# B: 单个4×5的矩阵
B = torch.randn(4, 5)     # 形状: (4, 5)
 
# 广播过程:
# 1. B补全维度: (4, 5) → (1, 4, 5)
# 2. B扩展第一维: (1, 4, 5) → (2, 4, 5)
# 矩阵乘法: (2, 3, 4) @ (2, 4, 5) → (2, 3, 5)
result = A @ B            # 结果形状: (2, 3, 5)

 

 

 

随机初始化权重 + 广播的矩阵运算

import numpy as np

# 随机初始化权重矩阵 (3个神经元的输入层 → 2个神经元的输出层)
W = np.random.randn(2, 3) * 0.01  # 随机高斯分布

# 输入数据 (4个样本,每个样本3个特征)
X = np.random.rand(4, 3)  # 生成随机初始权重

# 广播机制实现全连接层
# W.shape=(2,3), X.shape=(4,3) → 需要转置X使维度匹配
Z = np.dot(X, W.T)  # 广播:自动扩展维度计算 (4,3) @ (3,2) → (4,2)

print("输出矩阵形状:", Z.shape)  # (4, 2)

输出

输出矩阵形状: (4, 2)

批量数据添加随机噪声

import torch

# 生成真实数据 (100样本, 特征维度5)
data = torch.randn(100, 5)  # 生成同维度的随机噪声张量

# 创建随机噪声 (利用广播自动扩展到所有样本)
noise_intensity = 0.1
noise = noise_intensity * torch.randn(100, 5)  # 独立噪声

# 广播机制添加噪声 (相同形状直接相加)
noisy_data = data + noise

print("噪声数据示例:\n", noisy_data[:2])

输出

噪声数据示例:
 tensor([[ 1.5465,  1.0551, -1.5296, -0.8784,  1.1809],
        [ 1.0077, -0.1633,  1.2001, -0.9204,  0.8572]])

Dropout正则化实现

def dropout_layer(X, dropout_rate):
    if dropout_rate == 0: 
        return X
    # 生成随机掩码(利用广播保留原始维度)
    mask = (torch.rand(X.shape) > dropout_rate).float() #  torch.rand生成随机掩码
    # 缩放并应用掩码(广播到所有元素)
    return mask * X / (1 - dropout_rate)

# 测试
X = torch.ones(3, 4)
print("Dropout结果:\n", dropout_layer(X, 0.5))

输出

Dropout结果:
 tensor([[2., 2., 0., 2.],
        [0., 2., 2., 0.],
        [2., 0., 2., 0.]])

参数随机扰动 + 广播比较

# 模型参数
theta = np.array([1.0, -0.5, 2.0]) 

# 生成随机扰动方向 (广播到每个参数)
perturbation = np.random.choice([-0.1, 0.1], size=theta.shape)

# 评估两个候选参数
candidate1 = theta + perturbation
candidate2 = theta - perturbation

print(f"原始参数: {theta}")
print(f"扰动方向: {perturbation}")
print(f"候选1: {candidate1}\n候选2: {candidate2}")

输出

原始参数: [ 1.  -0.5  2. ]
扰动方向: [ 0.1  0.1 -0.1]
候选1: [ 1.1 -0.4  1.9]
候选2: [ 0.9 -0.6  2.1]

 

 

 

 

 @浙大疏锦行

 

 

你可能感兴趣的:(DAY48)