|
依据最大索引转向量:在最后一维上增加一个维度,将索引转化为一个浮点向量
import torch
from torch import nn
embedding = nn.Embedding(num_embeddings=8,
embedding_dim=3,
padding_idx=0)
index = torch.tensor([1,3,5,7])
print(embedding(index).shape) #torch.Size([4, 3])
|
import torch
from torch import nn
embedding = nn.Embedding(num_embeddings=8,
embedding_dim=3,
padding_idx=0)
index = torch.tensor([[1,3,5,7],[1,3,0,0]])
index=index.permute(1,0)
print(embedding(index).shape) #torch.Size([4, 2, 3])
|
|
manual_seed
import torch
from torch import nn
# 固定随机种子(关键步骤)
torch.manual_seed(42) # 可以是任意整数,但选定后要保持一致
embedding = nn.Embedding(num_embeddings=8,
embedding_dim=3,
padding_idx=0)
# 此时 embedding 的权重是固定的
index = torch.tensor([1, 3, 5, 7])
embed = embedding(index)
print(embed.shape) # torch.Size([4, 3])
embed
torch.Size([4, 3])
tensor([[-2.1055, 0.6784, -1.2345],
[-0.6866, -0.4934, 0.2415],
[-0.2168, -0.3097, -0.3957],
[-0.0631, -0.8286, 0.3309]], grad_fn=EmbeddingBackward0)
直接初始化 nn.Embedding 的权重(更精确控制)
import torch
from torch import nn
# 自定义固定的初始化权重(示例:简单递增的值)
fixed_weight = torch.tensor([
[0.0, 0.0, 0.0], # padding_idx=0 的向量(全零)
[0.1, 0.1, 0.1], # index=1
[0.2, 0.2, 0.2], # index=2
[0.3, 0.3, 0.3], # index=3
[0.4, 0.4, 0.4], # index=4
[0.5, 0.5, 0.5], # index=5
[0.6, 0.6, 0.6], # index=6
[0.7, 0.7, 0.7], # index=7
])
embedding = nn.Embedding(num_embeddings=8,
embedding_dim=3,
padding_idx=0)
embedding.weight.data = fixed_weight # 直接赋值
index = torch.tensor([1, 3, 5, 7])
embed = embedding(index)
print(embed.shape) # torch.Size([4, 3])
print(embed)
关键点说明 torch.manual_seed(seed) 设置随机种子后,nn.Embedding 的权重初始化会固定,但每次修改代码或运行环境变化时可能仍会不同。 直接赋值 weight.data 完全控制权重值,适合需要可重复实验的场景(例如论文复现)。 padding_idx 的影响 如果指定了 padding_idx(如本例的 0),对应索引的向量会始终为全零,不受随机种子影响。 |
|
|
|
|
num_embeddings nn.Embedding中num_embeddings理论上指索引的个数, 但这有个前提,索引编码从0开始,并且一个连一个, 不能跳跃,一般情况下也不会跳跃,但跳跃也没有关系 实际上num_embeddings指提供的索引中的最大值 比如,本例如果num_embeddings低于8将报错,而实际上的索引个数只有4个 正常情况下索引编码都是从0开始,也无跳跃
|
|
nn.Embedding模板类生成的对象 import torch from torch import nn embedding = nn.Embedding(num_embeddings=6,embedding_dim=3,padding_idx=0) batch_vec = torch.arange(start=0,end=6,step=1).reshape(2,3) embedding(batch_vec).shape # torch.Size([2, 3, 3]) 该对象将索引矩阵升了一维,所升的这一维就是索引所转向量的维度, pytorch的维度是这样的(dim=0,dim=1), 升的这一维默认放在更高的维度,就是(dim=0,dim=1,dim=2)
|
|
随机性与有效性:起点是随机的,终点是有效的(但不一定是最好的,)
import torch
from torch import nn
embedding = nn.Embedding(num_embeddings=6,embedding_dim=3,padding_idx=0)
batch_vec = torch.arange(start=0,end=6,step=1).reshape(2,3)
embedding(batch_vec)
tensor([[[ 0.0000, 0.0000, 0.0000],
[-0.9986, 0.2995, -1.3050],
[-0.8627, 0.4689, -0.1170]],
[[-0.3458, 1.2517, -0.7372],
[ 0.4307, -0.3824, 0.1640],
[-1.2211, 1.0763, 1.4638]]], grad_fn=EmbeddingBackward0)
AI所要训练的参数是在定义nn.Embedding模板类时初始化的 nn.Embedding模板类在初始化参数时,是随机的, 这样随机地将一个整数索引转换为n维浮点向量,有效吗? 其实它的思想跟神经网络层的思想是一样的,参数随机初始化, 在训练时梯度下降,逐步向不随机的方向,就是标签的方向靠近 随机当然是无效的,训练后才有效 |
|
|
|
import numpy as np
from tpf.nlp import IndexEmbed
embed = IndexEmbed()
index = np.array([1,2,3])
embed.embedding(index,embedding_dim=2)
tensor([[ 0.7980, -0.0897],
[ 0.0561, 0.2836],
[-0.5602, 1.4158]])
embed.embedding(index,embedding_dim=5)
tensor([[-0.8093, -2.0782, -1.1509, 0.5586, -3.9801],
[-0.6414, -1.3621, 0.1242, -1.0882, 0.4275],
[ 0.5396, -0.7445, 0.6825, 0.5504, -1.4078]])
embedding_dim 映射到6维及以上维度时,还需要指定 num_embeddings
或者说,需要更加灵活的映射关系时,指定embedding_dim,num_embeddings
本功能的关键是
- 记录参数文件,格式为 f"embed_{num_embeddings}_{embedding_dim}"
- 第二次加载时,相同的索引会生成相同的向量
embed.embedding(index, embedding_dim=6, num_embeddings=100000)
指定文件前缀
import numpy as np
from tpf.nlp import IndexEmbed
embed = IndexEmbed(file_pre="/tmp/embed")
index = np.array([1,2,3])
embed.embedding(index,embedding_dim=2)
生成文件 $ ls -ltrh /tmp/embed_* -rw-rw-r-- 1 llm llm 2.1K Jul 4 17:15 /tmp/embed_9_2 -rw-rw-r-- 1 llm llm 3.2K Jul 4 17:15 /tmp/embed_99_3 -rw-rw-r-- 1 llm llm 18K Jul 4 17:15 /tmp/embed_999_4 -rw-rw-r-- 1 llm llm 20M Jul 4 17:15 /tmp/embed_999999_5 -rw-rw-r-- 1 llm llm 2.3M Jul 4 17:15 /tmp/embed_100000_6 可以看到num_embeddings越大时,参数占用的空间也是越大的 file_pre为None则表示不记录文件
import numpy as np
from tpf.nlp import IndexEmbed
embed = IndexEmbed()
index = np.array([1,2,3])
embed.embedding(index,embedding_dim=2)
tensor([[ 0.7980, -0.0897],
[ 0.0561, 0.2836],
[-0.5602, 1.4158]])
此时生成随机向量仍然是固定的,因为设置了随机种子,但这种固定没有存储为文件靠谱
- 可能重启服务或修改代码生成的随机向量就变了
|
|
添加forward方法
import numpy as np
from tpf.nlp import IndexEmbed
embed = IndexEmbed()
index = np.array([1,2,3])
embed(index)
tensor([[ 0.7980, -0.0897],
[ 0.0561, 0.2836],
[-0.5602, 1.4158]])
embed(index,embedding_dim=3)
tensor([[-0.0369, -1.0962, 0.0523],
[ 1.1494, 0.5489, 0.6164],
[ 0.9435, -0.7968, -2.2954]])
embed(index,embedding_dim=3,num_embeddings=1000)
tensor([[-0.0369, -1.0962, 0.0523],
[ 1.1494, 0.5489, 0.6164],
[ 0.9435, -0.7968, -2.2954]])
---------------------------------------------------------------------------------- |
import numpy as np
import pandas as pd
import torch
from torch import nn
# 设置随机种子以便结果可复现
np.random.seed(42)
columns = ['feature_value_1', 'is_feature_value_535', 'is_feature_value_536']
data = {
col: np.random.randint(0, 10, size=5) for col in columns
}
df = pd.DataFrame(data)
df
from tpf.nlp import ClsIndexEmbed
cls_dim_dict = {
'is_feature_value_535': 3,
'is_feature_value_536': 2
}
cie = ClsIndexEmbed()
df =cie(df,cls_dim_dict)
df
指定文件前缀:如此索引编码永久固定 cie = ClsIndexEmbed(file_pre="/tmp/aa/embed") df =cie(df,cls_dim_dict) df llm@ii:/opt/wks/aitpf$ ls -ltrh /tmp/aa/ total 20M -rw-rw-r-- 1 llm llm 2.1K Jul 9 16:15 embed_10_2 -rw-rw-r-- 1 llm llm 3.2K Jul 9 16:15 embed_100_3 -rw-rw-r-- 1 llm llm 18K Jul 9 16:15 embed_1000_4 -rw-rw-r-- 1 llm llm 20M Jul 9 16:15 embed_1000000_5 |
|
|
|
|