神经网络初始化实例化的维度与调用输入数据的维度

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

#from agents.helpers import SinusoidalPosEmb
class SinusoidalPosEmb(nn.Module):
def init(self, dim=16): #dim为初始化需要设置的参数 比如默认为16 计算后会升维
super().init()
self.dim = dim

def forward(self, x):
    device = x.device
    half_dim = self.dim // 2
    emb = math.log(10000) / (half_dim - 1)
    emb = torch.exp(torch.arange(half_dim, device=device) * -emb)
    emb = x[:, None] * emb[None, :]
    emb = torch.cat((emb.sin(), emb.cos()), dim=-1)
    return emb

class MLP(nn.Module):
“””
MLP Model
“””
def init(self, ##初始化以及参数
state_dim=2, #####初始化实例化定义的维度这个对看懂代码很关键! 与后面调用函数的输入数据的维度一般需要一致
action_dim=2,
device=“cpu”,
t_dim=16):

    super(MLP, self).__init__()
    self.device = "cpu"

    self.time_mlp = nn.Sequential(
        SinusoidalPosEmb(t_dim),  #  这个是初始化为16维度
        nn.Linear(t_dim, t_dim * 2),
        nn.Mish(),
        nn.Linear(t_dim * 2, t_dim),
    )

    input_dim = state_dim + action_dim + t_dim ## 2+2+16=20  维度数量
    self.mid_layer = nn.Sequential(nn.Linear(input_dim, 256),
                                   nn.Mish(),
                                   nn.Linear(256, 256),
                                   nn.Mish(),
                                   nn.Linear(256, 256),
                                   nn.Mish())

    self.final_layer = nn.Linear(256, action_dim)  ##输出2维度

def forward(self, x, time, state):  ##定义个方法

    t = self.time_mlp(time)
    x = torch.cat([x, t, state], dim=1)  ###第二个维度以后要一致
    x = self.mid_layer(x)

    return self.final_layer(x)

MLPinstance=MLP()#初始化一个实例
MLPinstance

######################
x = torch.rand(5, 1, 2) # [10, 1, 8] #bath_size,1,2维度
time=5 #标量不对
state=torch.rand(5, 1, 2)
x.shape
torch.tensor(range(5)).unsqueeze(1).unsqueeze(2).shape,torch.rand(5, 1, 2).shape #有什么区别?

这两个 torch.tensor 的操作创建了不同形状和内容的张量。

1. torch.tensor(range(5)).unsqueeze(1).unsqueeze(2)

– 首先,torch.tensor(range(5)) 创建了一个一维张量,内容为 [0, 1, 2, 3, 4]

– 然后,.unsqueeze(1) 在第1个维度(现在是一维张量的唯一维度,等同于插入一个新的列维度)添加一个维度,使得形状变为 (5, 1)

– 接着,.unsqueeze(2) 再次在新维度的后面添加一个维度,最终形状变为 (5, 1, 1)。因此,这个操作的结果是一个形状为 (5, 1, 1) 的张量,每个元素都是从0到4的数字,每一行重复同一个数字,并且在最后两个维度上只有一个单位。

2. torch.rand(5, 1, 2)

– 这个操作直接创建了一个形状为 (5, 1, 2) 的三维张量,其中的所有元素都是从0到1之间的随机数(均匀分布)。这意味着你得到的是一个有5行,每行包含一个大小为1的子列表,每个子列表内有2个随机数的张量。

总结:

– 形状不同:前者形状为 (5, 1, 1),主要由连续的整数构成;后者形状为 (5, 1, 2),由随机浮点数构成。

– 内容不同:前者的内容是确定的,是0到4的整数,每个数字沿最后一个维度重复;后者的内容是随机的,范围在0到1之间。

– 数据类型不同:默认情况下,前者(基于 range)会是整数类型(除非显式转换),而后者明确是浮点数类型,因为使用了 torch.rand

torch.tensor(range(5)).unsqueeze(1).unsqueeze(1).shape在那个维度后面升维度,torch.tensor(range(5)).unsqueeze(1).unsqueeze(2).shape

######################################

x = torch.rand(2, 1) # [10, 1, 8]
time=torch.tensor([5]) ##一维度的可以
state=torch.rand(2, 1)
x.shape

实例化SinusoidalPosEmb类

pos_emb = SinusoidalPosEmb(dim=16)

创建一个示例输入张量x

假设我们有一个序列长度为5,维度为16的输入

#x = torch.tensor(range(5)).unsqueeze(1).unsqueeze(2) # 形状为 [5, 1] bath size,以及对应的timestep
time = torch.tensor(time)
print(time.shape)

调用forward方法

positional_embedding = pos_emb(time)

##########################################################################

x = torch.rand(5, 1) # [10, 1, 8]
time= torch.tensor(range(5)).unsqueeze(1)#没必要这样 经过embedding后会增加一个维度
state=torch.rand(5, 1)
x.shape

#################################################################
x = torch.rand(5, 1)
time= torch.tensor([5])
state=torch.rand(5, 1)
x.shape,time.shape
#############################################成功调用的####################
x = torch.rand(5, 1) ####一般定义了2维度 所以一般输入的数据就是2个维度的多个元素 当然少于2维的运算后要能够升维度 或者运算后能够降低倒定义初始化中需要的的维度!!!!!!!!
time= torch.tensor(range(5))
state=torch.rand(5, 1)
x.shape,time.shape

torch.tensor([5]) 和torch.tensor(range(5))的维度有什么区别

torch.tensor([5]) 创建的是一个形状为 torch.Size([1]) 的张量,表示它是一个包含单个元素的一维张量。

torch.tensor(range(5)) 创建的是一个形状为 torch.Size([5]) 的张量,表示它是一个包含5个元素的一维张量。

MLPinstance(x,time,state) #成功调用

将位置索引 x 转换为形状 (5, 1),频率向量转换为形状 (1, 8) 是怎么理解请举例
当我们谈论将位置索引 x 转换为形状 (5, 1) 和频率向量转换为形状 (1, 8),我们实际上是在讨论在进行矩阵运算之前对张量(在PyTorch中,张量是多维数组)的形状调整,以便它们能够进行有效的点乘操作。这个过程通常称为“广播”(broadcasting),它允许不同形状的张量进行数学运算,只要它们在没有明确指定的维度上大小为1或者完全匹配。

例子说明:

位置索引 x

原始的位置索引 x 是一个一维张量,表示5个不同的位置:

x = torch.tensor([0, 1, 2, 3, 4])

形状是 (5,),表示有5个元素。

为了使其能与频率向量正确点乘,我们需要将其扩展成一个二维张量,形状变为 (5, 1)。这意味着每个位置现在被视为一个单独的行,每一行只有一个元素:

x_expanded = x.unsqueeze(1)
# x_expanded 的形状现在是 (5, 1),内容为:
# tensor([[0],
#         [1],
#         [2],
#         [3],
#         [4]])

通过 unsqueeze(1) 操作,我们在索引1的位置增加了一个新的维度,使得每个位置值变成一个单独的列向量。

频率向量

频率向量是基于一半的维度数(如果 dim=16,则 half_dim=8)创建的,假定我们已经计算了对应的频率值并存储在一个一维张量中:

freqs = torch.tensor([...])  # 假设这里填入了计算得到的频率值序列

其原始形状可能是 (8,),代表了8个不同频率的值。

为了点乘,我们需要将其调整为 (1, 8) 形状,意味着它变成了一个只有一行的矩阵:

freqs_expanded = freqs.unsqueeze(0)
# freqs_expanded 的形状现在是 (1, 8),内容保持原频率值不变,但结构上作为单行多列

通过 unsqueeze(0),我们在索引0的位置增加了一个新的维度,使频率值构成了一行向量。

结果

完成上述操作后,x_expandedfreqs_expanded 可以直接相乘,因为它们在第二个维度(列)上是匹配的(一个是1,另一个是8,但因为是点乘,一维会自动复制以匹配另一方的维度)。这样,每个位置的索引值会与所有的频率值进行一一对应乘法运算,从而生成最终的编码向量的一部分。

a为(5,3,1)的张量
b为(5,16)的张量 能否把b变为(5,3,16)的维度?
要将形状为 (5, 16) 的张量 b 转换成形状为 (5, 3, 16),以便它可以与形状为 (5, 3, 1) 的张量 a 在某些维度上进行运算,我们需要沿着一个新维度重复 b 中的每一行数据三次(因为 a 的第二个维度是 3)。这可以通过使用 torch.repeat_interleave 函数来完成,具体是沿着第1维度(在PyTorch中,维度索引从0开始计数,所以这是第二个维度)进行重复。

下面是操作的示例代码:

import torch

# 假设 b 是形状为 (5, 16) 的张量
b = torch.randn(5, 16)

# 将 b 调整为形状为 (5, 3, 16)
b_expanded = b.unsqueeze(1).repeat(1, 3, 1)

print("Original shape of b:", b.shape)
print("Expanded shape of b:", b_expanded.shape)

这段代码首先使用 unsqueeze(1)b 添加一个新的维度(变成 (5, 1, 16)),然后使用 repeat(1, 3, 1) 沿着新添加的维度复制数据三次,最终得到形状为 (5, 3, 16) 的张量。

这样调整后,b_expanded 就可以和形状为 (5, 3, 1) 的张量 a 在相应的维度上进行操作了,比如逐元素相乘等运算。

本站无任何商业行为
个人在线分享 » 神经网络初始化实例化的维度与调用输入数据的维度
E-->