第N4周:NLP中的文本嵌入
- 本文为365天深度学习训练营 中的学习记录博客
- 原作者:K同学啊
任务要求:加载第N1周的.txt文件,使用Embeddingbag与Embedding完成词嵌入
第N1周的.txt文件的名称为“任务文件.txt”,内容为:
比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。
为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:
词嵌入是一种用于自然语言处理 (NLP) 的技术,用于将单词表示为数字,以便计算机可以处理它们。通俗的讲就是,一种把文本转为数值输入到计算机中的方法。
在《第N1周:one-hot编码案例》中提到的将文本转换为字典序列、one-hot编码就是最早期的词嵌入方法。
Embedding和EmbeddingBag则是PyTorch中的用来处理文本数据中词嵌入(word embedding)的工具,它们将离散的词汇映射到低维的连续向量空间中,使得词汇之间的语义关系能够在向量空间中得到体现。
1.Embedding嵌入
Embedding是PyTorch中最基本的词嵌入操作,TensorFlow中也有相同的函数,功能是一样。它将每个离散的词汇映射到一个低维的连续向量空间中,并且保持了词汇之间的语义关系。在PyTorch中,Embedding的输入是一个整数张量,每个整数都代表着一个词汇的索引,输出是一个浮点型的张量,每个浮点数都代表着对应词汇的词嵌入向量。
●输入shape:[batch, seqSize](seqSize为单个文本长度)
●输出shape:[batch, seqSize, embed_dim](embed_dim嵌入维度)
嵌入层使用随机权重初始化,并将学习数据集中所有词的嵌入。它是一个灵活的层,可以以各种方式使用,如:
●它可以用作深度学习模型的一部分,其中嵌入与模型本身一起被学习。
●它可以用于加载训练好的词嵌入模型。
嵌入层被定义为网络的第一个隐藏层。
函数原型:
torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None,norm_type=2.0,scale_grad_by_freq=False, sparse=False,_weight=None,_freeze=False, device=None, dtype=None)
官方API地址:Embedding — PyTorch 2.0 documentation
常见参数:
1.num_embeddings:词汇表大小, 即,最大整数 index + 1。
2.embedding_dim:词向量的维度。
下面是一个简单的例子,用Embedding将两个句子转换为词嵌入向量:
1.1.自定义数据集类
import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader, Datasetclass MyDataset(Dataset):def __init__(self, texts, labels):self.texts = textsself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):texts = self.texts[idx]labels = self.labels[idx]return texts, labels
1.2.定义填充函数
def collate_batch(batch):texts, labels = zip(*batch)max_len = max(len(text) for text in texts)padded_texts = [F.pad(text, (0, max_len - len(text)), value=0) for text in texts]padded_texts = torch.stack(padded_texts)labels = torch.tensor(labels, dtype=torch.float).unsqueeze(1)return padded_texts, labels
1.3.准备数据和数据加载器
# 假设我们有以下三个样本,分别由不同数量的单词索引组成
text_data = [torch.tensor([1, 1, 1, 1], dtype=torch.long), # 样本1torch.tensor([2, 2, 2], dtype=torch.long), # 样本2torch.tensor([3, 3], dtype=torch.long) # 样本3
]# 对应的标签
labels = torch.tensor([4, 5, 6], dtype=torch.float)# 创建数据集和数据加载器
my_dataset = MyDataset(text_data, labels)
data_loader = DataLoader(my_dataset, batch_size=2, shuffle=True, collate_fn=collate_batch)for batch in data_loader:print(batch)
代码输出
(tensor([[1, 1, 1, 1],[2, 2, 2, 0]]), tensor([[4.],[5.]]))
(tensor([[3, 3]]), tensor([[6.]]))
1.4.定义模型
class EmbeddingModel(nn.Module):def __init__(self, vocab_size, embed_dim):super(EmbeddingModel, self).__init__()self.embedding = nn.Embedding(vocab_size, embed_dim)self.fc = nn.Linear(embed_dim, 1) # 假设我们做一个二分类任务def forward(self, text): print("embedding输入文本是:",text)print("embedding输入文本shape:",text.shape)embedding = self.embedding(text)embedding_mean = embedding.mean(dim=1) # 对每个样本的嵌入向量进行平均print("embedding输出文本shape:",embedding_mean.shape)return self.fc(embedding_mean)
特别注意:
如果使用embedding_mean = embedding.mean(dim=1)语句对每个样本的嵌入向量求平均,输出shape为[batch, embed_dim]。若注释掉该语句,输出shape则为[batch, seqSize, embed_dim]。
1.5.训练模型
# 示例词典大小和嵌入维度
vocab_size = 10
embed_dim = 6# 创建模型实例
model = EmbeddingModel(vocab_size, embed_dim)# 定义一个简单的损失函数和优化器
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
for epoch in range(1): # 训练1个epochfor batch in data_loader:texts, labels = batch# 前向传播outputs = model(texts)loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()print(f'Epoch {epoch+1}, Loss: {loss.item()}')
代码输出
embedding输入文本是: tensor([[3, 3, 0],[2, 2, 2]])
embedding输入文本shape: torch.Size([2, 3])
embedding输出文本shape: torch.Size([2, 6])embedding输入文本是: tensor([[1, 1, 1, 1]])
embedding输入文本shape: torch.Size([1, 4])
embedding输出文本shape: torch.Size([1, 6])Epoch 1, Loss: 1.4471522569656372
2.EmbeddingBag嵌入
EmbeddingBag是在Embedding基础上进一步优化的工具,其核心思想是将每个输入序列的嵌入向量进行合并,能够处理可变长度的输入序列,并且减少了计算和存储的开销,并且可以计算句子中所有词汇的词嵌入向量的均值或总和。
在PyTorch中,EmbeddingBag的输入是一个 整数张量 和一个 偏移量张量,每个整数都代表着一个词汇的索引,偏移量则表示句子中每个词汇的位置,输出是一个浮点型的张量,每个浮点数都代表着对应句子的词嵌入向量的均值或总和。
●输入shape:[seqsSize](seqsSize为单个batch文本总长度)
●输出shape:[batch, embed_dim](embed_dim嵌入维度)
假定原始输入数据为:[[1, 1, 1, 1],[2, 2, 2],[3, 3]]
1.输入:
○输入是一个展平的词汇索引张量(input),例如 [2, 2, 2, 1, 1, 1, 1]。
○对应的偏移量(offsets),例如 [0, 3],表示每个样本在展平张量中的起始位置。
2.合并操作:
○根据偏移量,将嵌入向量进行合并操作。
○合并操作可以是求和、平均或取最大值,默认是平均(mean)。
函数原型:
torch.nn.EmbeddingBag(num_embeddings, embedding_dim, max_norm=None, norm_type=2.0, scale_grad_by_freq=False, mode='mean', sparse=False, _weight=None, include_last_offset=False, padding_idx=None, device=None, dtype=None)
主要参数:
●num_embeddings (int):词典的大小。
●embedding_dim (int):每个词向量的维度,即嵌入向量的长度。
●mode (str):指定嵌入向量的聚合方式。可选值为 ‘sum’、‘mean’ 和 ‘max’。
○(假设有一个序列 [2, 3, 1],每个数字表示一个离散特征的索引,对应的嵌入向量分别为 [[0.1, 0.2, 0.3],[0.2, 0.3, 0.4],[0.3, 0.4, 0.5]])
○’sum’:对所有的嵌入向量求和,则使用 ‘sum’ 模式汇总后的嵌入向量为 [0.6, 0.9,1.2]。
○’mean’:对所有的嵌入向量求平均值,使用 ‘mean’ 模式汇总后的嵌入向量为 [0.2,0.3, 0.4]。
○’max’:对所有的嵌入向量求最大值,使用 ‘max’ 模式汇总后的嵌入向量为 [0.3,0.4,0.5]。
下面是一个简单的例子,用EmbeddingBag将两个句子转换为词嵌入向量并计算它们的均值。
2.1.自定义数据集类
import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader, Datasetclass MyDataset(Dataset):def __init__(self, texts, labels):self.texts = textsself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):texts = self.texts[idx]labels = self.labels[idx]return texts, labels
2.2.准备数据和数据加载器
# 假设我们有以下三个样本,分别由不同数量的单词索引组成
text_data = [torch.tensor([1, 1, 1, 1], dtype=torch.long), # 样本1torch.tensor([2, 2, 2], dtype=torch.long), # 样本2torch.tensor([3, 3], dtype=torch.long) # 样本3
]# 对应的标签
labels = torch.tensor([4, 5, 6], dtype=torch.float)# 创建数据集和数据加载器
my_dataset = MyDataset(text_data, labels)
data_loader = DataLoader(my_dataset, batch_size=2, shuffle=True, collate_fn=lambda x: x)for batch in data_loader:print(batch)
代码输出
[(tensor([1, 1, 1, 1]), tensor(4.)), (tensor([2, 2, 2]), tensor(5.))]
[(tensor([3, 3]), tensor(6.))]
2.3.定义模型
class EmbeddingBagModel(nn.Module):def __init__(self, vocab_size, embed_dim):super(EmbeddingBagModel, self).__init__()self.embedding_bag = nn.EmbeddingBag(vocab_size, embed_dim, mode='mean')self.fc = nn.Linear(embed_dim, 1) # 假设我们做一个二分类任务def forward(self, text, offsets):print("embedding_bag输入文本是:",text)print("embedding_bag输入文本shape:",text.shape)embedded = self.embedding_bag(text, offsets)print("embedding_bag输出文本shape:",embedded.shape)return self.fc(embedded)
2.4.训练模型
# 示例词典大小和嵌入维度
vocab_size = 10
embed_dim = 6# 创建模型实例
model = EmbeddingBagModel(vocab_size, embed_dim)# 定义一个简单的损失函数和优化器
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
for epoch in range(1): # 训练1个epochfor batch in data_loader:# 将批处理的数据展平并计算偏移量texts, labels = zip(*batch)offsets = [0] + [len(text) for text in texts[:-1]]offsets = torch.tensor(offsets).cumsum(dim=0)texts = torch.cat(texts)labels = torch.tensor(labels).unsqueeze(1)# 前向传播outputs = model(texts, offsets)loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()print(f'Epoch {epoch+1}, Loss: {loss.item()}')
代码输出
embedding_bag输入文本是: tensor([1, 1, 1, 1, 2, 2, 2])
embedding_bag输入文本shape: torch.Size([7])
embedding_bag输出文本shape: torch.Size([2, 6])embedding_bag输入文本是: tensor([3, 3])
embedding_bag输入文本shape: torch.Size([2])
embedding_bag输出文本shape: torch.Size([1, 6])Epoch 1, Loss: 11.76957893371582
3.用Embedding嵌入处理txt文件内容
3.1.自定义数据集类
import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader, Datasetclass MyDataset(Dataset):def __init__(self, texts, labels):self.texts = textsself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):texts = self.texts[idx]labels = self.labels[idx]return texts, labels
3.2.定义填充函数
def collate_batch(batch):texts, labels = zip(*batch)max_len = max(len(text) for text in texts)padded_texts = [F.pad(text, (0, max_len - len(text)), value=0) for text in texts]padded_texts = torch.stack(padded_texts)labels = torch.tensor(labels, dtype=torch.float).unsqueeze(1)return padded_texts, labels
3.3.准备数据和数据加载器
import torch
import torch.nn.functional as F
import jieba# 打开txt文件
file_name = "./N1/任务文件.txt"
with open(file_name,"r",encoding = "utf-8") as file:context = file.read()texts = context.split()
texts# 使用结巴分词进行分词
tokenized_texts = [list(jieba.cut(text)) for text in texts]# 构建词汇表
word_index = {}
index_word = {}
for i, word in enumerate(set([word for text in tokenized_texts for word in text])):word_index[word] = iindex_word[i] = word# 将文本转化为整数序列
sequences = [[word_index[word] for word in text] for text in tokenized_texts]# 获取词汇表大小
vocab_size = len(word_index)# 将整数序列转化为one-hot编码
one_hot_results = torch.zeros(len(texts), vocab_size)
for i, seq in enumerate(sequences):one_hot_results[i, seq] = 1# 打印结果
print("词汇表:")
print(word_index)
print("\n文本:")
print(texts)
print("\n分词结果")
print(tokenized_texts)
print("\n文本序列:")
print(sequences)
print("\nOne-Hot编码:")
print(one_hot_results)
代码输出
词汇表:
{'one': 0, '了': 1, '基本': 2, '类别': 3, '如下': 4, '实际上': 5, '-': 6, '其中': 7, '避免': 8, '情况': 9, '就是': 10, '存在': 11, '独立': 12, ')': 13, '实际意义': 14, '的': 15, '到': 16, '2': 17, '使用': 18, '提到': 19, '不同': 20, '一个': 21, '用': 22, '可以': 23, '例如': 24, '会': 25, '问题': 26, '相互': 27, '不': 28, '可能': 29, '之间': 30, '这些': 31, '编码方式': 32, '是': 33, '顺序': 34, '思想': 35, '将': 36, '分别': 37, '地': 38, '1': 39, '值': 40, '模型': 41, '有': 42, '比较': 43, '。': 44, '为': 45, '、': 46, '或': 47, '这种': 48, '0': 49, '映射': 50, '上面': 51, '只有': 52, '元素': 53, '独热': 54, '和': 55, '认为': 56, '距离': 57, '对于': 58, '称': 59, '其余': 60, '具有': 61, '编码': 62, '引入': 63, '关系': 64, '这样': 65, '为了': 66, '直观': 67, '也': 68, '字典': 69, '或者': 70, ',': 71, '三个': 72, '向量': 73, '错误': 74, '3': 75, 'hot': 76, '但是': 77, '采用': 78, '(': 79, '每个': 80, ':': 81, '序列': 82, '表示': 83, '而': 84, '一些': 85, '这': 86}文本:
['比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。', '为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:']分词结果
[['比较', '直观', '的', '编码方式', '是', '采用', '上面', '提到', '的', '字典', '序列', '。', '例如', ',', '对于', '一个', '有', '三个', '类别', '的', '问题', ',', '可以', '用', '1', '、', '2', '和', '3', '分别', '表示', '这', '三个', '类别', '。', '但是', ',', '这种', '编码方式', '存在', '一个', '问题', ',', '就是', '模型', '可能', '会', '错误', '地', '认为', '不同', '类别', '之间', '存在', '一些', '顺序', '或', '距离', '关系', ',', '而', '实际上', '这些', '关系', '可能', '是', '不', '存在', '的', '或者', '不', '具有', '实际意义', '的', '。'], ['为了', '避免', '这种', '问题', ',', '引入', '了', 'one', '-', 'hot', '编码', '(', '也', '称', '独热', '编码', ')', '。', 'one', '-', 'hot', '编码', '的', '基本', '思想', '是', '将', '每个', '类别', '映射', '到', '一个', '向量', ',', '其中', '只有', '一个', '元素', '的', '值', '为', '1', ',', '其余', '元素', '的', '值', '为', '0', '。', '这样', ',', '每个', '类别', '之间', '就是', '相互', '独立', '的', ',', '不', '存在', '顺序', '或', '距离', '关系', '。', '例如', ',', '对于', '三个', '类别', '的', '情况', ',', '可以', '使用', '如下', '的', 'one', '-', 'hot', '编码', ':']]文本序列:
[[43, 67, 15, 32, 33, 78, 51, 19, 15, 69, 82, 44, 24, 71, 58, 21, 42, 72, 3, 15, 26, 71, 23, 22, 39, 46, 17, 55, 75, 37, 83, 86, 72, 3, 44, 77, 71, 48, 32, 11, 21, 26, 71, 10, 41, 29, 25, 74, 38, 56, 20, 3, 30, 11, 85, 34, 47, 57, 64, 71, 84, 5, 31, 64, 29, 33, 28, 11, 15, 70, 28, 61, 14, 15, 44], [66, 8, 48, 26, 71, 63, 1, 0, 6, 76, 62, 79, 68, 59, 54, 62, 13, 44, 0, 6, 76, 62, 15, 2, 35, 33, 36, 80, 3, 50, 16, 21, 73, 71, 7, 52, 21, 53, 15, 40, 45, 39, 71, 60, 53, 15, 40, 45, 49, 44, 65, 71, 80, 3, 30, 10, 27, 12, 15, 71, 28, 11, 34, 47, 57, 64, 44, 24, 71, 58, 72, 3, 15, 9, 71, 23, 18, 4, 15, 0, 6, 76, 62, 81]]One-Hot编码:
tensor([[0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 1., 1., 0., 0., 1., 1., 0., 1.,0., 1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 0.,0., 1., 1., 1., 0., 1., 1., 1., 1., 0., 1., 1., 1., 0., 0., 1., 0., 0.,0., 1., 1., 1., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 1., 1., 1.,1., 0., 1., 1., 0., 1., 1., 0., 0., 0., 1., 1., 1., 1., 1.],[1., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 0.,1., 0., 0., 1., 0., 1., 1., 0., 1., 1., 1., 0., 1., 0., 0., 1., 1., 1.,1., 0., 0., 1., 1., 0., 0., 0., 1., 1., 0., 1., 1., 1., 1., 0., 1., 1.,1., 0., 0., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 0., 1., 0., 0., 1.,1., 1., 0., 0., 1., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0.]])
# 将文本序列转换为PyTorch张量
text_data = [torch.tensor(seq, dtype=torch.long) for seq in sequences]
# 假设标签是一些浮点数值(根据实际任务定义标签)
labels = torch.tensor([1.0, 2.0], dtype=torch.float)
# 输出结果
print("Text Data:", text_data)
print("Labels:", labels)
代码输出
Text Data: [tensor([43, 67, 15, 32, 33, 78, 51, 19, 15, 69, 82, 44, 24, 71, 58, 21, 42, 72,3, 15, 26, 71, 23, 22, 39, 46, 17, 55, 75, 37, 83, 86, 72, 3, 44, 77,71, 48, 32, 11, 21, 26, 71, 10, 41, 29, 25, 74, 38, 56, 20, 3, 30, 11,85, 34, 47, 57, 64, 71, 84, 5, 31, 64, 29, 33, 28, 11, 15, 70, 28, 61,14, 15, 44]), tensor([66, 8, 48, 26, 71, 63, 1, 0, 6, 76, 62, 79, 68, 59, 54, 62, 13, 44,0, 6, 76, 62, 15, 2, 35, 33, 36, 80, 3, 50, 16, 21, 73, 71, 7, 52,21, 53, 15, 40, 45, 39, 71, 60, 53, 15, 40, 45, 49, 44, 65, 71, 80, 3,30, 10, 27, 12, 15, 71, 28, 11, 34, 47, 57, 64, 44, 24, 71, 58, 72, 3,15, 9, 71, 23, 18, 4, 15, 0, 6, 76, 62, 81])]
Labels: tensor([1., 2.])
# 创建数据集和数据加载器
my_dataset = MyDataset(text_data, labels)
data_loader = DataLoader(my_dataset, batch_size=2, shuffle=True, collate_fn=collate_batch)for batch in data_loader:print(batch)
代码输出
(tensor([[43, 67, 15, 32, 33, 78, 51, 19, 15, 69, 82, 44, 24, 71, 58, 21, 42, 72,3, 15, 26, 71, 23, 22, 39, 46, 17, 55, 75, 37, 83, 86, 72, 3, 44, 77,71, 48, 32, 11, 21, 26, 71, 10, 41, 29, 25, 74, 38, 56, 20, 3, 30, 11,85, 34, 47, 57, 64, 71, 84, 5, 31, 64, 29, 33, 28, 11, 15, 70, 28, 61,14, 15, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0],[66, 8, 48, 26, 71, 63, 1, 0, 6, 76, 62, 79, 68, 59, 54, 62, 13, 44,0, 6, 76, 62, 15, 2, 35, 33, 36, 80, 3, 50, 16, 21, 73, 71, 7, 52,21, 53, 15, 40, 45, 39, 71, 60, 53, 15, 40, 45, 49, 44, 65, 71, 80, 3,30, 10, 27, 12, 15, 71, 28, 11, 34, 47, 57, 64, 44, 24, 71, 58, 72, 3,15, 9, 71, 23, 18, 4, 15, 0, 6, 76, 62, 81]]), tensor([[1.],[2.]]))
3.4.定义模型
class EmbeddingModel(nn.Module):def __init__(self, vocab_size, embed_dim):super(EmbeddingModel, self).__init__()self.embedding = nn.Embedding(vocab_size, embed_dim)self.fc = nn.Linear(embed_dim, 1) # 假设我们做一个二分类任务def forward(self, text):print("embedding输入文本是:",text)print("embedding输入文本shape:",text.shape)embedding = self.embedding(text)embedding_mean = embedding.mean(dim=1) # 对每个样本的嵌入向量进行平均print("embedding输出文本shape:",embedding_mean.shape)return self.fc(embedding_mean)
3.5.训练模型
# 示例词典大小和嵌入维度
vocab_size = vocab_size
embed_dim = 10# 创建模型实例
model = EmbeddingModel(vocab_size, embed_dim)# 定义一个简单的损失函数和优化器
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
for epoch in range(1): # 训练1个epochfor batch in data_loader:texts, labels = batch# 前向传播outputs = model(texts)loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()print(f'Epoch {epoch+1}, Loss: {loss.item()}')
代码输出
embedding输入文本是: tensor([[43, 67, 15, 32, 33, 78, 51, 19, 15, 69, 82, 44, 24, 71, 58, 21, 42, 72,3, 15, 26, 71, 23, 22, 39, 46, 17, 55, 75, 37, 83, 86, 72, 3, 44, 77,71, 48, 32, 11, 21, 26, 71, 10, 41, 29, 25, 74, 38, 56, 20, 3, 30, 11,85, 34, 47, 57, 64, 71, 84, 5, 31, 64, 29, 33, 28, 11, 15, 70, 28, 61,14, 15, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0],[66, 8, 48, 26, 71, 63, 1, 0, 6, 76, 62, 79, 68, 59, 54, 62, 13, 44,0, 6, 76, 62, 15, 2, 35, 33, 36, 80, 3, 50, 16, 21, 73, 71, 7, 52,21, 53, 15, 40, 45, 39, 71, 60, 53, 15, 40, 45, 49, 44, 65, 71, 80, 3,30, 10, 27, 12, 15, 71, 28, 11, 34, 47, 57, 64, 44, 24, 71, 58, 72, 3,15, 9, 71, 23, 18, 4, 15, 0, 6, 76, 62, 81]])
embedding输入文本shape: torch.Size([2, 84])
embedding输出文本shape: torch.Size([2, 10])
Epoch 1, Loss: 0.9843546152114868
4.EmbeddingBag嵌入处理txt文件内容
4.1.自定义数据集类
import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader, Datasetclass MyDataset(Dataset):def __init__(self, texts, labels):self.texts = textsself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):texts = torch.tensor(self.texts[idx], dtype=torch.long)labels = torch.tensor(self.labels[idx], dtype=torch.float)return texts, labels
4.2.准备数据和数据加载器
import torch
import torch.nn.functional as F
import jieba# 打开txt文件
file_name = "./N1/任务文件.txt"
with open(file_name,"r",encoding = "utf-8") as file:context = file.read()texts = context.split()
texts# 使用结巴分词进行分词
tokenized_texts = [list(jieba.cut(text)) for text in texts]# 构建词汇表
word_index = {}
index_word = {}
for i, word in enumerate(set([word for text in tokenized_texts for word in text])):word_index[word] = iindex_word[i] = word# 将文本转化为整数序列
sequences = [[word_index[word] for word in text] for text in tokenized_texts]# 获取词汇表大小
vocab_size = len(word_index)# 将整数序列转化为one-hot编码
one_hot_results = torch.zeros(len(texts), vocab_size)
for i, seq in enumerate(sequences):one_hot_results[i, seq] = 1# 打印结果
print("词汇表:")
print(word_index)
print("\n文本:")
print(texts)
print("\n分词结果")
print(tokenized_texts)
print("\n文本序列:")
print(sequences)
print("\nOne-Hot编码:")
print(one_hot_results)
代码输出
词汇表:
{'one': 0, '了': 1, '基本': 2, '类别': 3, '如下': 4, '实际上': 5, '-': 6, '其中': 7, '避免': 8, '情况': 9, '就是': 10, '存在': 11, '独立': 12, ')': 13, '实际意义': 14, '的': 15, '到': 16, '2': 17, '使用': 18, '提到': 19, '不同': 20, '一个': 21, '用': 22, '可以': 23, '例如': 24, '会': 25, '问题': 26, '相互': 27, '不': 28, '可能': 29, '之间': 30, '这些': 31, '编码方式': 32, '是': 33, '顺序': 34, '思想': 35, '将': 36, '分别': 37, '地': 38, '1': 39, '值': 40, '模型': 41, '有': 42, '比较': 43, '。': 44, '为': 45, '、': 46, '或': 47, '这种': 48, '0': 49, '映射': 50, '上面': 51, '只有': 52, '元素': 53, '独热': 54, '和': 55, '认为': 56, '距离': 57, '对于': 58, '称': 59, '其余': 60, '具有': 61, '编码': 62, '引入': 63, '关系': 64, '这样': 65, '为了': 66, '直观': 67, '也': 68, '字典': 69, '或者': 70, ',': 71, '三个': 72, '向量': 73, '错误': 74, '3': 75, 'hot': 76, '但是': 77, '采用': 78, '(': 79, '每个': 80, ':': 81, '序列': 82, '表示': 83, '而': 84, '一些': 85, '这': 86}文本:
['比较直观的编码方式是采用上面提到的字典序列。例如,对于一个有三个类别的问题,可以用1、2和3分别表示这三个类别。但是,这种编码方式存在一个问题,就是模型可能会错误地认为不同类别之间存在一些顺序或距离关系,而实际上这些关系可能是不存在的或者不具有实际意义的。', '为了避免这种问题,引入了one-hot编码(也称独热编码)。one-hot编码的基本思想是将每个类别映射到一个向量,其中只有一个元素的值为1,其余元素的值为0。这样,每个类别之间就是相互独立的,不存在顺序或距离关系。例如,对于三个类别的情况,可以使用如下的one-hot编码:']分词结果
[['比较', '直观', '的', '编码方式', '是', '采用', '上面', '提到', '的', '字典', '序列', '。', '例如', ',', '对于', '一个', '有', '三个', '类别', '的', '问题', ',', '可以', '用', '1', '、', '2', '和', '3', '分别', '表示', '这', '三个', '类别', '。', '但是', ',', '这种', '编码方式', '存在', '一个', '问题', ',', '就是', '模型', '可能', '会', '错误', '地', '认为', '不同', '类别', '之间', '存在', '一些', '顺序', '或', '距离', '关系', ',', '而', '实际上', '这些', '关系', '可能', '是', '不', '存在', '的', '或者', '不', '具有', '实际意义', '的', '。'], ['为了', '避免', '这种', '问题', ',', '引入', '了', 'one', '-', 'hot', '编码', '(', '也', '称', '独热', '编码', ')', '。', 'one', '-', 'hot', '编码', '的', '基本', '思想', '是', '将', '每个', '类别', '映射', '到', '一个', '向量', ',', '其中', '只有', '一个', '元素', '的', '值', '为', '1', ',', '其余', '元素', '的', '值', '为', '0', '。', '这样', ',', '每个', '类别', '之间', '就是', '相互', '独立', '的', ',', '不', '存在', '顺序', '或', '距离', '关系', '。', '例如', ',', '对于', '三个', '类别', '的', '情况', ',', '可以', '使用', '如下', '的', 'one', '-', 'hot', '编码', ':']]文本序列:
[[43, 67, 15, 32, 33, 78, 51, 19, 15, 69, 82, 44, 24, 71, 58, 21, 42, 72, 3, 15, 26, 71, 23, 22, 39, 46, 17, 55, 75, 37, 83, 86, 72, 3, 44, 77, 71, 48, 32, 11, 21, 26, 71, 10, 41, 29, 25, 74, 38, 56, 20, 3, 30, 11, 85, 34, 47, 57, 64, 71, 84, 5, 31, 64, 29, 33, 28, 11, 15, 70, 28, 61, 14, 15, 44], [66, 8, 48, 26, 71, 63, 1, 0, 6, 76, 62, 79, 68, 59, 54, 62, 13, 44, 0, 6, 76, 62, 15, 2, 35, 33, 36, 80, 3, 50, 16, 21, 73, 71, 7, 52, 21, 53, 15, 40, 45, 39, 71, 60, 53, 15, 40, 45, 49, 44, 65, 71, 80, 3, 30, 10, 27, 12, 15, 71, 28, 11, 34, 47, 57, 64, 44, 24, 71, 58, 72, 3, 15, 9, 71, 23, 18, 4, 15, 0, 6, 76, 62, 81]]One-Hot编码:
tensor([[0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 1., 1., 0., 0., 1., 1., 0., 1.,0., 1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 0.,0., 1., 1., 1., 0., 1., 1., 1., 1., 0., 1., 1., 1., 0., 0., 1., 0., 0.,0., 1., 1., 1., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 1., 1., 1.,1., 0., 1., 1., 0., 1., 1., 0., 0., 0., 1., 1., 1., 1., 1.],[1., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 0.,1., 0., 0., 1., 0., 1., 1., 0., 1., 1., 1., 0., 1., 0., 0., 1., 1., 1.,1., 0., 0., 1., 1., 0., 0., 0., 1., 1., 0., 1., 1., 1., 1., 0., 1., 1.,1., 0., 0., 1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 0., 1., 0., 0., 1.,1., 1., 0., 0., 1., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0.]])
# 分词后的文本和对应的标签
text_data = sequences# 对应的标签
# 假设有两个标签
labels = [0, 1]# 创建数据集和数据加载器
my_dataset = MyDataset(text_data, labels)
data_loader = DataLoader(my_dataset, batch_size=2, shuffle=True, collate_fn=lambda x: x)for batch in data_loader:print(batch)
代码输出
[(tensor([66, 8, 48, 26, 71, 63, 1, 0, 6, 76, 62, 79, 68, 59, 54, 62, 13, 44,0, 6, 76, 62, 15, 2, 35, 33, 36, 80, 3, 50, 16, 21, 73, 71, 7, 52,21, 53, 15, 40, 45, 39, 71, 60, 53, 15, 40, 45, 49, 44, 65, 71, 80, 3,30, 10, 27, 12, 15, 71, 28, 11, 34, 47, 57, 64, 44, 24, 71, 58, 72, 3,15, 9, 71, 23, 18, 4, 15, 0, 6, 76, 62, 81]), tensor(1.)), (tensor([43, 67, 15, 32, 33, 78, 51, 19, 15, 69, 82, 44, 24, 71, 58, 21, 42, 72,3, 15, 26, 71, 23, 22, 39, 46, 17, 55, 75, 37, 83, 86, 72, 3, 44, 77,71, 48, 32, 11, 21, 26, 71, 10, 41, 29, 25, 74, 38, 56, 20, 3, 30, 11,85, 34, 47, 57, 64, 71, 84, 5, 31, 64, 29, 33, 28, 11, 15, 70, 28, 61,14, 15, 44]), tensor(0.))]
4.3.定义模型
class EmbeddingBagModel(nn.Module):def __init__(self, vocab_size, embed_dim):super(EmbeddingBagModel, self).__init__()self.embedding_bag = nn.EmbeddingBag(vocab_size, embed_dim, mode='mean')self.fc = nn.Linear(embed_dim, 1) # 假设我们做一个二分类任务def forward(self, text, offsets):print("embedding_bag输入文本是:",text)print("embedding_bag输入文本shape:",text.shape)embedded = self.embedding_bag(text, offsets)print("embedding_bag输出文本shape:",embedded.shape)return self.fc(embedded)
4.4.训练模型
# 示例词典大小和嵌入维度
vocab_size = vocab_size
embed_dim = 6# 创建模型实例
model = EmbeddingBagModel(vocab_size, embed_dim)# 定义一个简单的损失函数和优化器
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)# 训练模型
for epoch in range(1): # 训练1个epochfor batch in data_loader:# 将批处理的数据展平并计算偏移量texts, labels = zip(*batch)offsets = [0] + [len(text) for text in texts[:-1]]offsets = torch.tensor(offsets).cumsum(dim=0)texts = torch.cat(texts)labels = torch.tensor(labels).unsqueeze(1)# 前向传播outputs = model(texts, offsets)loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()print(f'Epoch {epoch+1}, Loss: {loss.item()}')
代码输出
embedding_bag输入文本是: tensor([43, 67, 15, 32, 33, 78, 51, 19, 15, 69, 82, 44, 24, 71, 58, 21, 42, 72,3, 15, 26, 71, 23, 22, 39, 46, 17, 55, 75, 37, 83, 86, 72, 3, 44, 77,71, 48, 32, 11, 21, 26, 71, 10, 41, 29, 25, 74, 38, 56, 20, 3, 30, 11,85, 34, 47, 57, 64, 71, 84, 5, 31, 64, 29, 33, 28, 11, 15, 70, 28, 61,14, 15, 44, 66, 8, 48, 26, 71, 63, 1, 0, 6, 76, 62, 79, 68, 59, 54,62, 13, 44, 0, 6, 76, 62, 15, 2, 35, 33, 36, 80, 3, 50, 16, 21, 73,71, 7, 52, 21, 53, 15, 40, 45, 39, 71, 60, 53, 15, 40, 45, 49, 44, 65,71, 80, 3, 30, 10, 27, 12, 15, 71, 28, 11, 34, 47, 57, 64, 44, 24, 71,58, 72, 3, 15, 9, 71, 23, 18, 4, 15, 0, 6, 76, 62, 81])
embedding_bag输入文本shape: torch.Size([159])
embedding_bag输出文本shape: torch.Size([2, 6])
Epoch 1, Loss: 0.711330235004425
相关文章:
第N4周:NLP中的文本嵌入
本文为365天深度学习训练营 中的学习记录博客原作者:K同学啊 任务要求:加载第N1周的.txt文件,使用Embeddingbag与Embedding完成词嵌入 第N1周的.txt文件的名称为“任务文件.txt”,内容为: 比较直观的编码方式是采用上…...
C++高精度减法
高精度减法其实跟加法差不多,首先就是需要逆序存入整数数组,其次就是做运算,最后就是删除前导0逆序输出。 不过在做高精度减法需要考虑一下两个数的关系是有三种的,a>b,a<b ab;思考全面咱们的程序才能拿满分。 以下是完整…...
protobuf cmakelist,msvc utf-8设置
源字符集和执行字符集 源字符集指的是cpp文件中字符串的编码方式 执行字符集指的是exe文件中字符串的编码方式 msvc编译器设置的命令行参数 /source-charset:utf-8 /execution-charset:utf-8 cmake中设置 add_compile_options(“ < < <<CXX_COMPILER_ID:MSVC>…...
Haproxy讲解
Haproxy: haproxy是一个开源的高性能反向代理和负载均衡器,主要用于TCP和HTTP流量管理。 功能和特点:haproxy能够处理大量的并发连接,支持TCP和HTTP协议,具有高可用性和负载均衡功能。它特别适用于需要处理大量流量的网站&am…...
K8S系列——一、Ubuntu上安装Helm
在使用K8S搭建集群服务时,有时候需要用到Helm(一个用于Kubernetes应用管理的工具),下面是在Ubuntu上安装Helm的过程。 1.更新系统软件包列表 sudo apt-get update2.安装必要的依赖项 sudo apt-get install apt-transport-https…...
排序: 插入\希尔\选择\归并\冒泡\快速\堆排序实现
1.排序的概念及应用 1.1概念 排序:所谓排序,就是一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 1.2运用 购物筛选排序: 1.3常见排序算法 2.实现常见的排序算法 int a[ {5,3,9,6,2,4,7,1,8}; 2…...
OpenCV图像处理——按最小外接矩形剪切图像处理ROI后映射回原图像
引言 在图像处理过程中,提取感兴趣区域(ROI)并在其上进行处理后,往往需要将处理后的结果映射回原图像。这一步通常涉及以下几个步骤: 找到最小外接矩形:使用 cv::boundingRect 或 cv::minAreaRect 提取感兴…...
Linux中以单容器部署Nginx+ASP.NET Core
强烈推荐在生产环境中使用反向代理服务器转发请求到Kestrel Http服务器,本文将会实践将Nginx --->ASP.NET Core 部署架构容器化的过程。 Nginx->ASP.NET Coe部署架构容器化 在Docker中部署Nginx--->ASP.NETCore 有两种选择, 第一种是在单容器…...
【秋招笔试】8.11大疆秋招(第三套)-三语言题解
🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收…...
标题:打造编程学习的知识宝库:高效笔记记录与整理
标题:打造编程学习的知识宝库:高效笔记记录与整理 在编程学习的征途中,有效的笔记记录和整理技巧对于掌握和回顾知识点至关重要。本文将从笔记工具选择、笔记结构设计、以及实践与复习策略三个方面,探讨如何高效地记录并整理编程…...
【Rust光年纪】Rust 官方提供的关键工具概览:代码检查、格式化和依赖管理
提升 Rust 项目质量和安全性:掌握官方工具的核心功能和使用方法 前言 Rust 作为一种系统编程语言,拥有强大的性能和内存安全特性。然而,随着项目规模增长,代码检查、格式化和依赖管理等工作变得更加重要。因此,Rust …...
【Python学习-UI界面】PyQt5 小部件8-QSlider 数值滑动
样式如下: QSlider 类对象为用户提供一个沟槽,可以在其上移动一个手柄。 它是一个经典的小部件,用于控制有界值。 手柄在沟槽上的位置相当于控件的下限和上限之间的整数。 常用方法如下: 序号方法描述1setMinimum设置滑块的最小值2setMax…...
MapReduce入门教程
这可不是目录 入门定义与说明数据分析Map和Reduce阶段的任务<Kn,Vn>分析MapReduce的数据类型其他说明(持续更新) 开发案例(持续更新)自定义的wordcountcsv文件操作序列化操作 入门 定义与说明 数据分析 以下未数据分析示意图 Map和Reduce阶段的任务 Map阶段的任务&a…...
JDBC1 Mysql驱动,连接数据库
JDBC 一、JDBC Java Database Connectivity:Java访问数据库的解决方案 JDBC定义了一套标准接口,即访问数据库的通用API, 不同的数据库厂商根据各自数据库的特点去实现这些接口。 JDBC希望用相同的方式访问不同的数据库,让具体的…...
LeetCode 205 同构字符串
题目 给定两个字符串 s 和 t ,判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,…...
ARM高性能计算(HPC)处理器Neoverse介绍
思考: Neoverse系列中的N、V、E有什么区别? 这三个字母的缩写又是什么? ARM Neoverse架构是ARM专为服务器、数据中心、高性能计算(HPC)和网络基础设施设计的一系列处理器架构。Neoverse架构分为N系列、V系列和E系列,这些系列面向不同的应用场景,各自有不同的设计目标和…...
【每日力扣中医养生】力扣1298. 你能从盒子里获得的最大糖果数
1298. 你能从盒子里获得的最大糖果数 文章目录 【每日力扣&中医养生】力扣1298. 你能从盒子里获得的最大糖果数题目描述示例解析示例 1示例 2 算法思路算法步骤代码实现复杂度分析总结 【每日力扣&中医养生】力扣1298. 你能从盒子里获得的最大糖果数 《黄帝内经》的阴…...
大数据-81 Spark 安装配置环境 集群环境配置 超详细 三台云服务器
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
C#创建一个自定义控件类
如果你希望在 TextBox 内部嵌入一个按钮,并且这个按钮用于打开文件选择对话框,可以创建一个自定义控件来实现这一功能。下面是一个示例,展示如何在 Windows 窗体应用程序中创建一个自定义控件,其中 Button 嵌入到 TextBox 内部。 …...
springboot牙科就诊管理系统--论文源码调试讲解
2 相关技术 2.1 MySQL数据库 本设计用到的数据库就是MySQL数据库[3],之所以用到这个数据库的原因很多。首先,从满足功能需求上面来讲,MySQL是符合的;其次,从学习程度来讲,MySQL相比其他数据库不管是从安装…...
CUDA+tensorflow+python+vscode在GPU下环境安装及问题汇总与解答
2024.8.14 因为要做深度学习,需要安装tensorflowgpu的环境,每次都搞不好整的很生气,本次将安装过程中参考的一些大佬的博客和安装过程中遇到的问题及解决方案总结一下,希望以后不要在这件事情上浪费时间。安装环境其实也没有想象中…...
24/8/14算法笔记 复习_逻辑回归sigmoid
import numpy as np import matplotlib.pyplot as pltdef sigmoid(x):return 1/(1np.exp(-x))x np.linspace(-5,5,100) y sigmoid(x)plt.plot(x,y,colorgreen) #损失函数 from sklearn import datasets from sklearn.linear_model import LogisticRegression from mpl_toolki…...
MySQL忘记/无root密码,强制修改root密码
MySQL忘记/无root密码,强制修改root密码_mysql无root密码登录后设置密码-CSDN博客 sudo vi /etc/mysql/my.cnf 添加如下内容: [mysqld] skip-grant-tablessudo service mysql restart mysql -u root -p use mysql; update mysql.user set authentica…...
探索 MongoDB 的 $currentDate:解决 TTL 时间不同步问题的利器
在我们日常的开发工作中,时间管理是一个非常重要的环节。尤其是在处理数据库中的数据时,时间戳的准确性和一致性至关重要。今天,我们要聊聊 MongoDB 中的一个神奇操作符——$currentDate,它是如何帮助我们解决 TTL(Tim…...
defineModel
前言 随着 Vue3.4 版本的发布,defineModel 也正式转正了。它可以简化父子组件之间的双向绑定,是目前官方推荐的双向绑定实现方式。 defineModel 使用 在开发的过程中,如果有需要通过子组件进行状态更新的话,v-model是一个绕不开…...
去中心化技术的崛起:探索Web3的新时代
引言: Web3是互联网发展的新阶段,它通过去中心化技术重新定义了数字世界的运作方式。这一新时代不仅带来了技术上的突破,也为社会互动和数据管理开辟了新的前景。本文将深入探讨Web3的核心技术、应用领域、全球影响以及面临的挑战࿰…...
GNU/Linux - copy_{to,from}_user: 用户和内核空间的内存互拷贝
copy_{to,from}_user 函数是 Linux 内核编程的基本组成部分。它用于将数据从用户空间复制到内核空间。在编写内核模块或使用设备驱动程序时,安全地处理用户空间和内核空间之间的数据传输对防止安全漏洞和确保系统稳定至关重要。 The copy_{to,from}_user function i…...
进阶岛任务1: 探索 InternLM 模型能力边界
任务 https://aicarrier.feishu.cn/wiki/QjBswYlmdiSGfskq6vNcBmZCn09 在 CompassArena 中选择双模型对话,与InternLM2.5及另外任意其他模型对话,收集 5 个 InternLM2.5 输出结果不如其他模型的对话案例,以及 InternLM2.5 的 5 个 Good Ca…...
RabbitMQ实现多线程处理接收消息
前言:在使用RabbitListener注解来指定消费方法的时候,默认情况是单线程去监听队列,但是这个如果在高并发的场景中会出现很多个任务,但是每次只消费一个消息,就会很缓慢。单线程处理消息容易引起消息处理缓慢࿰…...
AI智能网关 边缘计算 视觉AI
随着人工智能技术的不断发展,AI智能网关正成为连接现实世界和虚拟智能世界的重要桥梁。作为智能化时代的关键设备,AI智能网关在物联网、工业、市政、无人驾驶、农业、环保、水利等领域起到了至关重要的作用。 首先,AI智能网关是物联网的核…...
linux搭建个人网站/马鞍山seo
数据结构实验三二叉树实验报告数据结构实验报告实验名称: 实验三——二叉树学生姓名: XX班 级:班内序号:学 号:日 期:1.实验要求1.1实验目的通过选择下面两个题目之一进行实现,掌握如…...
物流公司网站方案/seo专业课程
只说下思路吧,毕竟把加密代码公开对别网站不好。如有权益问题可以发私信联系我删除,或q:1847858794 如图有个desc加密参数和fingerPrint: fingerPrint参数也是加密来的,代表的是浏览器指纹,加密前的内容是一些浏览器特…...
怎么在id导入wordpress/小红书推广方案
我这里使用了DoTween插件 下载 请在Unity 的Asset Store里下载 实例代码如下: using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening;public class TuBiao : MonoBehaviour {//创建一个变量 用来改变小图标 是上 还是下 的动…...
做综合医院网站/免费的个人网站html代码
Document.get获取记录数据,或获取根据查询条件筛选后的记录数据函数签名如下:function get(options?: object): Promise参数说明options 为可选参数,是一个如下格式的对象,如传入 success、fail、complete 三者之一,则…...
wordpress摘要全部显示/整合营销传播策划方案
我们的手机在很多的情况下都会遇到打不开网页的情况,那这个时候,我们该怎么办呢?首先你可以检查WiFi是否连接,接着看下手机数据网络有没有打开,再查看网速是否正常,最后检查手机内存大小。下面就给大家讲一…...
外贸网站如何seo推广/做关键词优化
一些官方提供的Frank-Cucumber代码,可以参考去写我们自己的自动化测试代码 WAIT_TIMEOUT 240require rspec/expectations# -- See -- # Then /^I wait to see "([^\"]*)"$/ do |expected_mark|Timeout::timeout(WAIT_TIMEOUT) dountil view_with_ma…...