深度学习每周学习总结N6:使用Word2vec实现文本分类

news2024/9/20 22:40:56
  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊 | 接辅导、项目定制

目录

    • 0. 总结:
      • 1.加载数据
      • 2. 构建词典
      • 3. 生成数据批次和迭代器
      • 4.模型搭建及初始化
      • 5. 定义训练与评估函数
      • 6. 拆分数据集并运行模型
      • 7. 结果可视化
      • 8. 测试指定数据
      • 9. 提问:与N4文本分类的异同
        • 分析代码
        • 数据处理方式
          • 1. 分词处理
          • 2. 构建词典
          • 3. 向量表示
        • 值得关注的点
          • 1. Word2Vec模型训练
          • 2. 文本向量化
          • 3. 数据加载和批处理
        • 模型结构
          • 1. 模型定义
        • 训练和评估
          • 1. 训练过程
        • 异同点总结
          • 共同点
          • 不同点
        • 值得学习的点

0. 总结:

之前有学习过文本预处理的环节,对文本处理的主要方式有以下三种:

1:词袋模型(one-hot编码)

2:TF-IDF

3:Word2Vec(词向量(Word Embedding) 以及Word2vec(Word Embedding 的方法之一))

详细介绍及中英文分词详见pytorch文本分类(一):文本预处理

上上上上期主要介绍Embedding,及EmbeddingBag 使用示例(对词索引向量转化为词嵌入向量) ,上上上期主要介绍:应用三种模型的英文分类

上上期将主要介绍中文基本分类(熟悉流程)、拓展:textCNN分类(通用模型)、拓展:Bert分类(模型进阶)

上期主要介绍Word2Vec,和nn.Embedding(), nn.EmbeddingBag()相比都是嵌入技术,用于将离散的词语或符号映射到连续的向量空间。

nn.Embeddingnn.EmbeddingBag 是深度学习框架(如 PyTorch)中的层,直接用于神经网络模型中,而 Word2Vec 是一种独立的词嵌入算法。

使用来说,如果需要在神经网络中处理变长序列的嵌入,可以选择 nn.EmbeddingBag;如果需要预训练词嵌入用于不同任务,可以选择 Word2Vec

本期主要介绍使用Word2Vec实现文本分类:

与N4文本分类的异同点总结

  • 共同点
    数据加载:都使用了PyTorch的DataLoader来批量加载数据。
    模型训练:训练过程大同小异,都是前向传播、计算损失、反向传播和梯度更新。
  • 不同点
    分词处理
    BERT模型:使用专门的BERT分词器。
    传统嵌入方法:通常使用jieba等工具进行分词。
    Word2Vec模型:假设数据已经分词。
    词向量表示
    BERT模型:使用BERT生成的上下文相关的词向量。
    传统嵌入方法:使用静态预训练词向量。
    Word2Vec模型:训练一个Word2Vec模型生成词向量。
    模型结构
    BERT模型:使用预训练的BERT模型作为编码器。
    传统嵌入方法:一般使用嵌入层+卷积/循环神经网络。
    Word2Vec模型:使用Word2Vec词向量和一个简单的线性分类器。
  • 值得学习的点
    词向量的使用:了解如何使用Word2Vec生成词向量并将其用于下游任务。
    数据预处理:不同方法的数据预处理方式,尤其是分词和词向量化的处理。
    模型训练:标准的模型训练和评估流程,尤其是损失计算、反向传播和梯度更新等步骤。
    超参数选择:注意学习率、批量大小和训练轮数等超参数的选择。
    通过这些比较和分析,可以更好地理解不同文本分类方法的优缺点以及适用场景。

1.加载数据

import torch
import torch.nn as nn
import warnings

from torch.utils.data import DataLoader,Dataset,random_split

import pandas as pd

warnings.filterwarnings('ignore')# 忽略警告信息
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device
device(type='cpu')
train_data = pd.read_csv('./data/N6-train.csv',sep='\t',header=None)
train_data
01
0还有双鸭山到淮阴的汽车票吗13号的Travel-Query
1从这里怎么回家Travel-Query
2随便播放一首专辑阁楼里的佛里的歌Music-Play
3给看一下墓王之王嘛FilmTele-Play
4我想看挑战两把s686打突变团竞的游戏视频Video-Play
.........
12095一千六百五十三加三千一百六十五点六五等于几Calendar-Query
12096稍小点客厅空调风速HomeAppliance-Control
12097黎耀祥陈豪邓萃雯畲诗曼陈法拉敖嘉年杨怡马浚伟等到场出席Radio-Listen
12098百事盖世群星星光演唱会有谁Video-Play
12099下周一视频会议的闹钟帮我开开Alarm-Update

12100 rows × 2 columns

class CustomDataset(Dataset):
    def __init__(self,texts,labels):
        self.texts = texts
        self.labels = labels
        
    def __len__(self):
        return len(self.texts)
    
    def __getitem__(self,idx):
        return self.texts[idx],self.labels[idx]
    
x = train_data[0].values[:]
y = train_data[1].values[:]

2. 构建词典

from gensim.models.word2vec import Word2Vec
import numpy as np

# 训练Word2Vec 浅层神经网络模型
w2v = Word2Vec(
    vector_size = 100, # 指特征向量的维度,默认为100
    min_count = 3      # 可以对字典做截断,词频少于min_count次数的单词会被丢弃掉,默认值为5
)
w2v.build_vocab(x)
w2v.train(
    x,
    total_examples = w2v.corpus_count,
    epochs = 20
)
(2733133, 3663560)

Word2Vec可以直接训练模型,一步到位。这里分了三步


第一步构建一个空模型


第二步使用 build_vocab 方法根据输入的文本数据 x 构建词典。build_vocab 方法会统计输入文本中每个词汇出现的次数,并按照词频从高到低的顺序将词汇加入词典中。


第三步使用 train 方法对模型进行训练,total_examples 参数指定了训练时使用的文本数量,这里使用的是 w2v.corpus_count 属性,表示输入文本的数量

如果一步到位的话代码为:

w2v = Word2Vec(x,vector_size=100,min_count=3,epochs=20)
# 将文本转化为向量
def average_vec(text):
    vec = np.zeros(100).reshape((1,100))
    for word in text:
        try:
            vec+= w2v.wv[word].reshape((1,100))
        except KeyError:
            continue
    return vec
# 将词向量保存为Ndarray
x_vec = np.concatenate([average_vec(z) for z in x])

# 保存 Word2Vec 模型及词向量
w2v.save('data/w2v_model.pkl')

这段代码定义了一个函数 average_vec(text),它接受一个包含多个词的列表 text 作为输入,并返回这些词对应词向量的平均值。该函数


首先初始化一个形状为 (1, 100) 的全零 numpy 数组来表示平均向量


然后遍历 text 中的每个词,并尝试从 Word2Vec 模型 w2v 中使用 wv 属性获取其对应的词向量。如果在模型中找到了该词,函数将其向量加到 vec 中。如果未找到该词,函数会继续迭代下一个词


最后,函数返回平均向量 vec

然后使用列表推导式将 average_vec() 函数应用于列表 x 中的每个元素。得到的平均向量列表使用 np.concatenate() 连接成一个 numpy 数组 x_vec,该数组表示 x 中所有元素的平均向量。x_vec 的形状为 (n, 100),其中 n 是 x 中元素的数量。

train_iter = CustomDataset(x_vec,y)
len(x),len(x_vec)
(12100, 12100)
label_name = list(set(train_data[1].values[:]))
label_name
['Audio-Play',
 'Radio-Listen',
 'Travel-Query',
 'TVProgram-Play',
 'Video-Play',
 'Other',
 'Music-Play',
 'Alarm-Update',
 'Weather-Query',
 'Calendar-Query',
 'FilmTele-Play',
 'HomeAppliance-Control']

3. 生成数据批次和迭代器

text_pipeline = lambda x:average_vec(x)
label_pipeline = lambda x:label_name.index(x)

lambda 表达式的语法为:lambda arguments: expression

其中 arguments 是函数的参数,可以有多个参数,用逗号分隔。expression 是一个表达式,它定义了函数的返回值。


text_pipeline 函数:接受一个包含多个词的列表 x 作为输入,并返回这些词对应词向量的平均值,即调用了之前定义的 average_vec 函数。这个函数用于将原始文本数据转换为词向量平均值表示的形式。


label_pipeline 函数:接受一个标签名 x 作为输入,并返回该标签名label_name 列表中的索引。这个函数可以用于将原始标签数据转换为数字索引表示的形式。

text_pipeline("你在干嘛")
array([[ 0.18396786,  0.24416898,  1.0977701 , -0.01573543, -2.34493342,
         0.14462006,  1.09909924,  0.72848918,  0.43942198, -0.36590184,
        -1.64841774, -4.0461483 ,  0.52117442, -0.93646932,  0.65021983,
         1.8863973 ,  3.21435681, -2.37889412,  4.38834111, -1.31753699,
         3.04073831, -1.56194845, -0.01702204, -0.26231994, -0.57977456,
        -0.59202761, -2.09177154, -0.93535494,  2.01195888, -2.03609261,
         2.05241142,  1.59645403, -0.09730234, -1.39273715,  0.35281967,
         0.07837144, -0.28004935,  3.58092116, -2.69026518,  1.25223976,
         0.26495122,  0.6858208 , -0.26904737,  1.87308259,  0.21092373,
         0.18170499,  2.06353265, -0.55430332, -2.19337641,  1.70870071,
         0.30772619, -2.93958779, -0.97791416,  0.84643018, -0.75232047,
        -0.05284989,  1.25495276, -0.59528226, -0.44547228,  0.5255087 ,
         0.86212044, -1.28084296,  2.38232671, -0.28152593, -0.64530418,
         1.20289534, -0.42659164,  0.95189874,  1.22811846,  0.04619575,
        -0.50489213,  0.27519883,  2.16535747, -0.17590564,  0.42813917,
        -0.09275024, -3.63906508,  0.53455901,  2.07623281, -0.39027843,
        -1.92971458,  0.42125694, -2.16986141,  2.77343564, -1.69743965,
        -1.50195191,  1.76218376, -1.49796952, -0.26446094, -0.30981308,
         0.9657587 , -1.63175048,  1.01593184,  0.9586434 ,  0.70671193,
        -2.49167663,  0.37804852,  0.94789429, -1.52659395,  0.88284026]])
label_pipeline("Travel-Query")
2
from torch.utils.data import DataLoader

def collate_batch(batch):
    label_list,text_list = [],[]
    
    for (_text,_label) in batch:
        # 标签列表
        label_list.append(label_pipeline(_label))
        
        # 文本列表
        processed_text = torch.tensor(text_pipeline(_text),dtype=torch.float32)
        text_list.append(processed_text)
        
    label_list = torch.tensor(label_list,dtype = torch.int64)
    text_list = torch.cat(text_list)
    
    return text_list.to(device),label_list.to(device)

4.模型搭建及初始化

from torch import nn

class TextClassificationModel(nn.Module):
    def __init__(self,num_class):
        super(TextClassificationModel,self).__init__()
        self.fc = nn.Linear(100,num_class)
    def forward(self,text):
        return self.fc(text)
# 模型初始化
num_class = len(label_name)
vocab_size = 100000
em_size = 12
model = TextClassificationModel(num_class).to(device)

5. 定义训练与评估函数

def train(dataloader):
    model.train()  # 切换为训练模式
    total_acc, total_loss, total_count = 0, 0, 0

    for idx, (text,label) in enumerate(dataloader):
        pred = model(text)
        
        optimizer.zero_grad()                    # grad属性归零
        loss = criterion(pred, label) # 计算网络输出和真实值之间的差距,label为真实值
        loss.backward()                          # 反向传播
        torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1) # 梯度裁剪
        optimizer.step()  # 每一步自动更新
        
        # 记录acc与loss
        total_acc   += (pred.argmax(1) == label).sum().item()
        total_loss  += loss.item()
        total_count += label.size(0)
        
    return total_acc / total_count, total_loss / total_count

def evaluate(dataloader):
    model.eval()  # 切换为测试模式
    total_acc, total_loss, total_count = 0, 0, 0

    with torch.no_grad():
        for idx, (text,label) in enumerate(dataloader):
            pred = model(text)
            
            loss = criterion(pred, label)  # 计算loss值
            # 记录测试数据
            total_acc   += (pred.argmax(1) == label).sum().item()
            total_loss  += loss.item()
            total_count += label.size(0)
            
    return total_acc/total_count, total_loss/total_count

torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1)是一个PyTorch函数,用于在训练神经网络时限制梯度的大小。这种操作被称为梯度裁剪(gradient clipping),可以防止梯度爆炸问题,从而提高神经网络的稳定性和性能。

在这个函数中:


model.parameters()表示模型的所有参数。对于一个神经网络,参数通常包括权重和偏置项。


0.1是一个指定的阈值,表示梯度的最大范数(L2范数)。如果计算出的梯度范数超过这个阈值,梯度会被缩放,使其范数等于阈值。

梯度裁剪的主要目的是防止梯度爆炸。梯度爆炸通常发生在训练深度神经网络时,尤其是在处理长序列数据的循环神经网络(RNN)中。当梯度爆炸时,参数更新可能会变得非常大,导致模型无法收敛或出现数值不稳定。通过限制梯度的大小,梯度裁剪有助于解决这些问题,使模型训练变得更加稳定。

6. 拆分数据集并运行模型

# 超参数
EPOCHS = 10 # epoch
LR = 5 # 学习率
BATCH_SIZE = 64 # batch size for training

criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=LR)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1.0, gamma=0.1)
total_accu = None

# 构建数据集
train_dataset = CustomDataset(train_data[0].values[:], train_data[1].values[:])

split_train_, split_valid_ = random_split(
    train_dataset,
    [int(len(train_dataset)*0.8), len(train_dataset) - int(len(train_dataset)*0.8)]
)
train_dataloader = DataLoader(split_train_, batch_size=BATCH_SIZE,
                              shuffle=True, collate_fn=collate_batch)
valid_dataloader = DataLoader(split_valid_, batch_size=BATCH_SIZE,
                              shuffle=True, collate_fn=collate_batch)

import copy
import time
epochs     = 10

train_loss = []
train_acc  = []
test_loss  = []
test_acc   = []

best_acc = 0    # 设置一个最佳准确率,作为最佳模型的判别指标

for epoch in range(epochs):
    # 更新学习率(使用自定义学习率时使用)
    # adjust_learning_rate(optimizer, epoch, learn_rate)
    epoch_start_time = time.time()
    
    epoch_train_acc, epoch_train_loss = train(train_dataloader)
    scheduler.step() # 更新学习率(调用官方动态学习率接口时使用)
    
    epoch_test_acc, epoch_test_loss = evaluate(valid_dataloader)
    
    # 保存最佳模型到 best_model
    if epoch_test_acc > best_acc:
        best_acc   = epoch_test_acc
        best_model = copy.deepcopy(model)
    
    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)
    
    # 获取当前的学习率
    lr = optimizer.state_dict()['param_groups'][0]['lr']
    
    template = ('Epoch:{:2d}, time: {:4.2f}s,Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%, Test_loss:{:.3f}, Lr:{:.2E}')
    print(template.format(epoch+1,time.time() - epoch_start_time,epoch_train_acc*100, epoch_train_loss, 
                          epoch_test_acc*100, epoch_test_loss, lr))
    
# 保存最佳模型到文件中
PATH = './best_model.pth'  # 保存的参数文件名
torch.save(model.state_dict(), PATH)

print('Done')

Epoch: 1, time: 0.94s,Train_acc:79.9%, Train_loss:0.021, Test_acc:85.5%, Test_loss:0.015, Lr:5.00E-01
Epoch: 2, time: 0.91s,Train_acc:88.8%, Train_loss:0.009, Test_acc:87.8%, Test_loss:0.009, Lr:5.00E-02
Epoch: 3, time: 0.91s,Train_acc:90.1%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.008, Lr:5.00E-03
Epoch: 4, time: 0.95s,Train_acc:90.1%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.008, Lr:5.00E-04
Epoch: 5, time: 0.91s,Train_acc:90.2%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.009, Lr:5.00E-05
Epoch: 6, time: 0.88s,Train_acc:90.2%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.008, Lr:5.00E-06
Epoch: 7, time: 0.87s,Train_acc:90.2%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.008, Lr:5.00E-07
Epoch: 8, time: 0.87s,Train_acc:90.2%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.008, Lr:5.00E-08
Epoch: 9, time: 0.91s,Train_acc:90.2%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.008, Lr:5.00E-09
Epoch:10, time: 0.92s,Train_acc:90.2%, Train_loss:0.007, Test_acc:88.1%, Test_loss:0.008, Lr:5.00E-10
Done

7. 结果可视化

import matplotlib.pyplot as plt
#隐藏警告
import warnings
warnings.filterwarnings("ignore")               #忽略警告信息
plt.rcParams['font.sans-serif']    = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False      # 用来正常显示负号
plt.rcParams['figure.dpi']         = 100        #分辨率

epochs_range = range(epochs)

plt.figure(figsize=(12, 3))
plt.subplot(1, 2, 1)

plt.plot(epochs_range, train_acc, label='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()


在这里插入图片描述

8. 测试指定数据

def predict(text, text_pipeline):
    with torch.no_grad():
        text = torch.tensor(text_pipeline(text), dtype=torch.float32)
        print(text.shape)
        output = model(text)
        return output.argmax(1).item()

# ex_text_str = "随便播放一首专辑阁楼里的佛里的歌"
ex_text_str = "还有双鸭山到淮阴的汽车票吗13号的"

model = model.to("cpu")

print("该文本的类别是:%s" %label_name[predict(ex_text_str, text_pipeline)])
torch.Size([1, 100])
该文本的类别是:Travel-Query

9. 提问:与N4文本分类的异同

分析代码

代码使用了Word2Vec技术将文本转化为词向量,并通过一个简单的线性分类器进行文本分类。以下是详细的分析和与之前两个模型(BERT和基于传统嵌入的方法)处理数据的方式的比较:

数据处理方式
1. 分词处理
  • BERT模型:使用了BERT的分词器(BertTokenizer),能够处理中文字符,并将其转换为BERT所需的输入格式,包括input_idsattention_mask
  • 传统嵌入方法:一般使用jieba进行分词,并通过词汇表将分词结果转换为索引。
  • Word2Vec模型:在代码中直接将句子传递给Word2Vec进行训练,假设句子已经被分好词。
2. 构建词典
  • BERT模型:直接使用预训练模型提供的词典(如bert-base-chinese)。
  • 传统嵌入方法:手动构建词汇表,并将词汇映射为索引。
  • Word2Vec模型:通过训练Word2Vec模型来构建词向量的词典。
3. 向量表示
  • BERT模型:使用BERT生成的上下文相关的词向量。
  • 传统嵌入方法:通常使用静态的预训练词向量(如Word2Vec或GloVe)。
  • Word2Vec模型:代码中训练了一个浅层的Word2Vec模型,并将每个词转换为一个100维的向量,句子表示为这些词向量的平均值。
值得关注的点
1. Word2Vec模型训练
from gensim.models.word2vec import Word2Vec
import numpy as np

# 训练Word2Vec 浅层神经网络模型
w2v = Word2Vec(
    vector_size=100,  # 指特征向量的维度
    min_count=3       # 词频少于min_count次数的单词会被丢弃
)
w2v.build_vocab(x)
w2v.train(x, total_examples=w2v.corpus_count, epochs=20)
  • 训练Word2Vec模型,这里使用的是Gensim库。vector_size参数设置了词向量的维度,min_count参数设置了词频少于3次的单词会被丢弃。
2. 文本向量化
# 将文本转化为向量
def average_vec(text):
    vec = np.zeros(100).reshape((1, 100))
    for word in text:
        try:
            vec += w2v.wv[word].reshape((1, 100))
        except KeyError:
            continue
    return vec
# 将词向量保存为Ndarray
x_vec = np.concatenate([average_vec(z) for z in x])
  • 使用Word2Vec模型将每个词转换为向量,并计算句子的平均向量。这里的句子表示为其包含词的词向量的平均值。
3. 数据加载和批处理
from torch.utils.data import DataLoader

def collate_batch(batch):
    label_list, text_list = [], []

    for (_text, _label) in batch:
        # 标签列表
        label_list.append(label_pipeline(_label))

        # 文本列表
        processed_text = torch.tensor(text_pipeline(_text), dtype=torch.float32)
        text_list.append(processed_text)

    label_list = torch.tensor(label_list, dtype=torch.int64)
    text_list = torch.cat(text_list)

    return text_list.to(device), label_list.to(device)
  • 这里的collate_batch函数用于将数据批处理成训练时所需的格式。text_pipelinelabel_pipeline分别用于处理文本和标签。
模型结构
1. 模型定义
class TextClassificationModel(nn.Module):
    def __init__(self, num_class):
        super(TextClassificationModel, self).__init__()
        self.fc = nn.Linear(100, num_class)

    def forward(self, text):
        return self.fc(text)
  • 这是一个简单的线性分类器,输入是100维的词向量,输出是分类的结果。
训练和评估
1. 训练过程
def train(dataloader):
    model.train()  # 切换为训练模式
    total_acc, total_loss, total_count = 0, 0, 0

    for idx, (text, label) in enumerate(dataloader):
        pred = model(text)

        optimizer.zero_grad()                    # grad属性归零
        loss = criterion(pred, label) # 计算网络输出和真实值之间的差距,label为真实值
        loss.backward()                          # 反向传播
        torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1) # 梯度裁剪
        optimizer.step()  # 每一步自动更新

        # 记录acc与loss
        total_acc += (pred.argmax(1) == label).sum().item()
        total_loss += loss.item()
        total_count += label.size(0)

    return total_acc / total_count, total_loss / total_count
  • 标准的训练过程,包括前向传播、计算损失、反向传播和梯度更新。
异同点总结
共同点
  1. 数据加载:都使用了PyTorch的DataLoader来批量加载数据。
  2. 模型训练:训练过程大同小异,都是前向传播、计算损失、反向传播和梯度更新。
不同点
  1. 分词处理

    • BERT模型:使用专门的BERT分词器。
    • 传统嵌入方法:通常使用jieba等工具进行分词。
    • Word2Vec模型:假设数据已经分词。
  2. 词向量表示

    • BERT模型:使用BERT生成的上下文相关的词向量。
    • 传统嵌入方法:使用静态预训练词向量。
    • Word2Vec模型:训练一个Word2Vec模型生成词向量。
  3. 模型结构

    • BERT模型:使用预训练的BERT模型作为编码器。
    • 传统嵌入方法:一般使用嵌入层+卷积/循环神经网络。
    • Word2Vec模型:使用Word2Vec词向量和一个简单的线性分类器。
值得学习的点
  1. 词向量的使用:了解如何使用Word2Vec生成词向量并将其用于下游任务。
  2. 数据预处理:不同方法的数据预处理方式,尤其是分词和词向量化的处理。
  3. 模型训练:标准的模型训练和评估流程,尤其是损失计算、反向传播和梯度更新等步骤。
  4. 超参数选择:注意学习率、批量大小和训练轮数等超参数的选择。

通过这些比较和分析,可以更好地理解不同文本分类方法的优缺点以及适用场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1990755.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

界面控件(无ui文件)

目录 菜单栏 工具栏 状态栏 停靠部件和核心部件 菜单栏 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {// 菜单栏,获取当前窗口的菜单栏,没有会自动创建一个QMenuBar *mb this->menuBar();// 添加菜单QMenu *menuFile mb-&g…

【ML】Pre-trained Language Models及其各种微调模型的实现细节和特点

Pre-trained Language Models及其各种微调模型的实现细节和特点 1. Pre-trained Language Models2. semi-supervised Learning3. zero-shot4. Parameter-Efficient Fine-Tuning4.1 含义:4.2 实现方式: 5. LoRA5.1 LoRA 的主要特点:5.2 LoRA 的…

【QT 5 QT 6 构建工具qmake-cmake-和-软件编译器MSVCxxxvs MinGWxxx说明】

【QT 5报错:/xxx/: error: ‘class Ui::frmMain’ has no member named ‘xxx’-和-软件编译器MSVCxxxvs MinGWxxx说明】 1、前言2 、qt 中 Qmake CMake 和 QBS1-qmake2-Cmake3-QBS4-官网一些说法5-各自特点 3、软件编译套件1-Desktop Qt 6.7.2 llvm-mingw 64-bit2-…

SpringBoot排除默认日志框架

默认用的logback application.properties中的配置无需改变,自动装配会根据条件(哪个日志的.class是否存在) 进行切换 只要切换日志配置文件就好 比如原来使用的logback-spring.xml换成log4j2-spring.xml 日志文件网上找找

Flink-DataWorks第三部分:数据集成(第59天)

系列文章目录 2.4 任务配置方式 2.4.1 DataStudio侧离线同步 2.4.1.1 开发流程概览 2.4.1.2 步骤一:新建离线同步节点 2.4.1.3 步骤二:配置同步网络链接 2.4.1.4 步骤三:配置数据来源与去向 2.4.1.5 步骤四:配置字段映射关系 2.4…

C:野指针介绍(定义、危害、规避)以及野指针与空指针的区分

目录 1、野指针 1.1 野指针的成因 1.指针未初始化 2.指针越界访问 3.指针指向的空间释放 1.2 野指针的危害 1.3 如何规避野指针 1. 指针初始化 2. 小心指针越界 3.指针变量不使用就及时赋上NULL 4. 指针使用前检查是否是空指针 5. 避免返回局部变量的地址 1.4 区…

微信小程序【五】摇骰子

摇骰子 一、dice.js二、dice.json三、dice.wxml四、dice.wxss 效果简述:点击设置“骰子个数”,喝一杯前,先摇一摇。 骰子图片命名示例: 1.png、2.png 一、dice.js Page({data: {numDice: 1, // 初始化骰子数diceImages: [],dic…

【iOS多线程(二)】GCD其他方法详解

GCD其他方法 dispatch_semaphore (信号量)什么是dispatch_semaphore(信号量)?dispatch_semaphore主要的三个方法dispatch_semaphore主要作用线程安全线程同步 dispatch_afterdispatch_time_t 两种形式 GCD 一次性代码(只执行一次&#xff09…

电脑维修店的主题源码 简洁wordpress企业主题模版下载

简洁wordpress企业主题,一个简洁的电脑维修店的主题 源码下载:https://download.csdn.net/download/m0_66047725/89612932 更多资源下载:关注我。

【深度学习】TTS,CosyVoice,推理部署的代码原理讲解分享

文章目录 demo代码加载配置文件speech_tokenizer_v1.onnx(只在zero_shot的时候使用)campplus.onnx(只为了提取说话人音色embedding)`campplus_model` 的作用代码解析具体过程解析总结示意图CosyVoiceFrontEndCosyVoiceModel推理过程总体推理过程推理速度很慢: https://git…

OpenNebula-6.9.80使用介绍

目录 准备:给宿主机添加一块网卡 1. 创建群组 2. 创建用户 3. 创建集群 4. 创建主机 5. 安全组 6. 网络模板 7. 虚拟网络 8. 导入镜像 9. 创建虚拟机模板 10. 实例化虚拟机 11. 卸载磁盘 12. 再次实例化 13. 添加新节点 14. 虚拟机迁移 准备&…

面壁的智能开源 MiniCPM-V 2.6 边缘人工智能多模态功能与 GPT-4V 不相上下

"MiniCPM-V2.6 "是一个边缘多模态人工智能模型,仅拥有 80 亿个参数,却在单图像、多图像和视频理解任务中取得了低于 200 亿个参数的三项 SOTA(艺术境界)成绩,显著增强了边缘多模态能力,并与 GPT-…

python.tkinter设计标记语言(转译2-html)

TOC 前言 本文只作为笔记记录。 前文我们已经通过TinText渲染器部分和TinML获得了test.tin解释后的标记内容列表。本文,我们将根据这个解释结果将Tin标记转为html文件。 转为html的好处 第一,Tin标记语言作为一个小小小小小项目,光把编写…

34-《球兰》

球兰 球兰(学名:Hoya carnosa(L.f.)R. Br),又名:马骝解、狗舌藤、铁脚板等,马利筋亚科球兰属多年生植物 。攀援灌木,附生于树上或石上,茎节上生气根。分布于云…

单链表-数据结构

一、单链表 1.结构定义 typedef struct LNode {int data;struct LNode* next; }LNode, * LinkList; 2.功能实现 ①创造结点 //创造结点 LNode* NewNode(int x) {struct LNode* ret (LNode*)malloc(sizeof(LNode));ret->data x;ret->next NULL;return ret; } ②插…

TypeError: (0 , _xxx.default) is not a function

1.首先从控制台报错信息看很让人疑惑,好像并没有这个函数,我这里是引入了address.js这个这个文件里面的函数导致的 2. 直接说原因:导入的函数不是default,但使用的时候没有使用"{}" import xxx from yyy 3.直接加上&q…

Golang | Leetcode Golang题解之第330题按要求补齐数组

题目&#xff1a; 题解&#xff1a; func minPatches(nums []int, n int) (patches int) {for i, x : 0, 1; x < n; {if i < len(nums) && nums[i] < x {x nums[i]i} else {x * 2patches}}return }

【vulnhub】Matrix:1靶机

靶机安装 下载地址&#xff1a;https://download.vulnhub.com/matrix/Machine_Matrix.zip 运行环境&#xff1a;VirtualBox 信息收集 靶机扫描 netdiscover -i eth0 -r 192.168.7.0/24 端口扫描&#xff0c;开放端口22、80、31337 nmap -A 192.168.7.203 -p- 目录扫描 d…

「C++系列」引用

文章目录 一、引用及定义引用的基本用法注意事项 二、引用与指针1. 定义和初始化2. 语法糖3. 空值4. 数组和函数5. 性能6. 用途 三、引用作为参数/返回值1. 把引用作为函数参数2. 把引用作为函数返回值 四、相关链接 一、引用及定义 在C中&#xff0c;引用&#xff08;Referen…

2025深圳国际户外用品暨跨境电商工厂选品展览会

2025深圳国际户外用品暨跨境电商工厂选品展览会 2025 Shenzhen International Outdoor Products and Cross border E-commerce Factory Selection Exhibition 时间&#xff1a;2025年02月27-3月01日 地点&#xff1a;深圳会展中心&#xff08;福田馆&#xff09; 详询主办方…