【AI达人创造营第二期】一文读懂textCNN模型原理

之前我们提到 CNN 时,通常会认为是属于计算机视觉领域。但是在2014年,Yoon Kim 针对 CNN 的输入层做了一些变形,从而提出了文本分类模型 textCNN。由于 CNN 在计算机视觉中,常被用于提取图像的局部特征图,且起到了很好的效果,所以该作者将其引入到 NLP 中,应用于文本分类任务,试图使用 CNN 捕捉文本中单词之间的关系。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【ai达人创造营第二期】一文读懂textcnn模型原理 - 创想鸟

一文读懂textCNN模型原理

一、简介

之前我们提到 CNN 时,通常会认为是属于计算机视觉领域。但是在2014年,Yoon Kim 针对 CNN 的输入层做了一些变形,从而提出了文本分类模型 textCNN。由于 CNN 在计算机视觉中,常被用于提取图像的局部特征图,且起到了很好的效果,所以该作者将其引入到 NLP 中,应用于文本分类任务,试图使用 CNN 捕捉文本中单词之间的关系。

二、与传统 CNN 的不同

【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

图一-textCNN架构

与传统图像的CNN网络相比, textCNN 在网络结构上没有任何变化,甚至更加简化了, 从图中可以看出textCNN 其实只有一层卷积,一层max-pooling, 最后将输出外接softmax 来n分类。

然而textCNN 最大的不同是在于输入数据的不同: 图像是二维甚至三维数据, 图像的卷积核是从左到右, 从上到下进行滑动来进行特征提取;自然语言是一维数据, 虽然经过word-embedding 生成了二维向量,但是对词向量做从左到右滑动来进行卷积没有意义。比如 “今天” 对应的向量[0, 0, 0, 0, 1], 按窗口大小为 1 * 2 从左到右滑动得到[0,0], [0,0], [0,0], [0, 1]这四个向量, 对应的都是”今天”这个词汇, 这种滑动没有帮助。

TextCNN最大优势在于网络结构简单 ,在模型网络结构如此简单的情况下,通过引入已经训练好的词向量依旧有很不错的效果,在多项数据数据集上超越benchmark。网络结构简单导致参数数目少, 计算量少, 训练速度快,在单机单卡的v100机器上,训练165万数据, 迭代26万步,半个小时左右可以收敛。

三、模型架构简析

《Convolutional Neural Networks for Sentence Classification》一文中最早给出了文本CNN的基本结构,而后《A Sensitivity Analysis …》一文专门做了各种控制变量的实验对比。

【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

图二-《Convolutional Neural Networks for Sentence Classification》模型示意图

【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

图三-《A Sensitivity Analysis …》[2]模型示意图

由于一条文本语句由 n 个词组成,而每个词又可以表示为一个 k 维的词向量,所以最初模型的输入可以看作是一个 n×k 的单通道图像。

之后经过卷积层处理。在卷积层中,选用了不同的卷积核来得到不同的特征图,且卷积核的宽度即词向量的维度 k,所以卷积在这里的作用是用于提取不同数量的单词构成的元组之间的关系,比如卷积核的大小为 3,那么则将相邻的三个词语当作是一个特征。

在上图一的第二个阶段可以看到,由于选用的卷积核宽度与词向量维度相同,所以最终得到的特征图也就表现为了 n 维向量,之后便是对得到的每一个特征图做一次max-pooling,并将max-pooling的结果作为全连接层的输入,并最终进行 Softmax 分类。

四、textCNN模型架构

我们仍以图一中文语句为例

(一)Word Embedding 分词构建词向量

如图一所示,textCNN 首先将 “今天天气很好,出来玩” 分词成”今天/天气/很好/,/出来/玩, 通过word2vec或者GLOV 等embedding 方式将每个词成映射成一个5维(维数可以自己指定)词向量, 如 “今天” -> [0,0,0,0,1], “天气” ->[0,0,0,1,0], “很好” ->[0,0,1,0,0]等等。【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

这样做的好处主要是将自然语言数值化,方便后续的处理。从这里也可以看出不同的映射方式对最后的结果是会产生巨大的影响, nlp 当中目前最火热的研究方向便是如何将自然语言映射成更好的词向量。我们构建完词向量后,将所有的词向量拼接起来构成一个6 * 5的二维矩阵,作为最初的输入。

(二)卷积池化层(convolution and pooling)

卷积(convolution)

文本卷积与图像卷积的不同之处在于只针对文本序列的一个方向(垂直)做卷积,卷积核的宽度固定为词向量的维度d。高度是超参数,可以设置。对句子单词每个可能的窗口做卷积操作得到特征图(feature map) c = [c_1, c_2, …, c_s-h+1]。

现在假设有一个卷积核,是一个宽度为d,高度为h的矩阵w,那么w有h∗d个参数需要被更新。对于一个句子,经过嵌入层之后可以得到矩阵AϵRs×d。 A[i:j]表示A的第i行到第j行, 那么卷积操作可以用如下公式表示:【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

叠加上偏置b,在使用激活函数f激活, 得到所需的特征。公式如下: 【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

具体卷积计算参考博客文本分类算法TextCNN原理详解(一)

对于多通道(channel)的说明

在CNN 中常常会提到一个词channel, 图三 中 深红矩阵与 浅红矩阵 便构成了两个channel 统称一个卷积核, 从这个图中也可以看出每个channel 不必严格一样, 每个4 * 5 矩阵与输入矩阵做一次卷积操作得到一个feature map. 在计算机视觉中,由于彩色图像存在 R, G, B 三种颜色, 每个颜色便代表一种channel。 【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

根据原论文作者的描述, 一开始引入channel 是希望防止过拟合(通过保证学习到的vectors 不要偏离输入太多)来在小数据集合获得比单channel更好的表现,后来发现其实直接使用正则化效果更好。

不过使用多channel 相比与单channel, 每个channel 可以使用不同的word embedding, 比如可以在no-static(梯度可以反向传播) 的channel 来fine tune 词向量,让词向量更加适用于当前的训练。

对于channel在textCNN 是否有用, 从论文的实验结果来看多channels并没有明显提升模型的分类能力, 七个数据集上的五个数据集 单channel 的textCNN 表现都要优于 多channels的textCNN。

最大池化(max-pooling)

【AI达人创造营第二期】一文读懂textCNN模型原理 - 创想鸟        

得到feamap = [1,1,2] 后, 从中选取一个最大值[2] 作为输出, 便是max-pooling。max-pooling 在保持主要特征的情况下, 大大降低了参数的数目, 从图五中可以看出 feature map 从 三维变成了一维, 好处有如下两点:

1、降低了过拟合的风险, feature map = [1, 1, 2] 或者[1, 0, 2] 最后的输出都是[2], 表明开始的输入即使有轻微变形, 也不影响最后的识别。

2、参数减少, 进一步加速计算。

pooling 本身无法带来平移不变性(图片有个字母A, 这个字母A 无论出现在图片的哪个位置, 在CNN的网络中都可以识别出来),卷积核的权值共享才能.

max-pooling的原理主要是从多个值中取一个最大值,做不到这一点。cnn 能够做到平移不变性,是因为在滑动卷积核的时候,使用的卷积核权值是保持固定的(权值共享), 假设这个卷积核被训练的就能识别字母A, 当这个卷积核在整张图片上滑动的时候,当然可以把整张图片的A都识别出来。

(三)优化与正则化

池化层后面加上全连接层和SoftMax层做分类任务,得到各个类别比如 label 为1 的概率以及label 为-1的概率。同时防止过拟合,一般会添加L2和Dropout正则化方法。最后整体使用梯度法进行参数的更新模型的优化。

五、案例与代码实现

本文案例参考飞桨项目THUCNews数据集使用TextCNN完成文本分类任务。案例采用 THUCNews 数据集,由清华大学自然语言处理实验室根据新浪新闻RSS订阅频道2005~2011年间的历史数据筛选过滤生成,包含74万篇新闻文档(2.19 GB),均为UTF-8纯文本格式。其在原始新浪新闻分类体系的基础上,重新整合划分出14个候选分类类别:财经、cai票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐。

(一)环境配置

In [1]

import pandas as pdimport numpy as npimport paddleimport paddle.nn as nnfrom paddle.io import DataLoader, Datasetimport paddle.optimizer as optimfrom paddlenlp.data import Padimport jiebafrom collections import Counter

   

(二)数据准备

In [2]

data = pd.read_csv("data/data45260/Train.txt", sep='t', names=['ClassNo', 'ClassName', 'Sentence'])print("Train Set")print(data.head())print(data.info())pred_data = pd.read_csv("data/data45260/Test.txt", sep='t', names=['Sentence'])print("Pred Set")print(pred_data.head())print(pred_data.info())

       

Train Set   ClassNo ClassName            Sentence0        0        财经        上证50ETF净申购突增1        0        财经        交银施罗德保本基金将发行2        0        财经  基金公司不裁员反扩军 走访名校揽人才3        0        财经  基金巨亏30亿 欲打开云天系跌停自救4        0        财经          基金市场周二缩量走低RangeIndex: 752476 entries, 0 to 752475Data columns (total 3 columns): #   Column     Non-Null Count   Dtype ---  ------     --------------   -----  0   ClassNo    752476 non-null  int64  1   ClassName  752476 non-null  object 2   Sentence   752475 non-null  objectdtypes: int64(1), object(2)memory usage: 17.2+ MBNonePred Set                  Sentence0  北京君太百货璀璨秋色 满100省353020元1        教育部:小学高年级将开始学习性知识2    专业级单反相机 佳能7D单机售价9280元3      星展银行起诉内地客户 银行强硬客户无奈4   脱离中国的实际 强压RMB大幅升值只能是梦想RangeIndex: 83599 entries, 0 to 83598Data columns (total 1 columns): #   Column    Non-Null Count  Dtype ---  ------    --------------  -----  0   Sentence  83599 non-null  objectdtypes: object(1)memory usage: 653.2+ KBNone

       In [3]

## 注意到训练集中语句与数据数目不匹配,需删除无效数据data.dropna(axis=0, how='any', inplace=True)X = data['Sentence'].valuesY = data['ClassNo'].valuesY_name = data['ClassName'][np.sort(np.unique(data['ClassName'], return_index=True)[1])].valuesY_dict = dict([val for val in zip(np.unique(Y), Y_name)])

   

数据预处理,中文语句的处理需要注意中文分词及停用词的去除。根据提供的中文停用词数据集,将其数据进行加载。然后使用 jieba 包提供的中文分词功能,将训练集的输入语句每一句首先进行分词,调用 jieba.lcut(s) 进行分词并且返回分词后的列表。对于列表中的每一个词语,查看是否在停用词表中出现,如果出现则将其删除。

In [4]

def preprocess(data):    stopwords = open("data/data81223/stopwords.txt").read().split('n')    new_data = []    for row in data:        row = jieba.lcut(row)  # 中文分词        new_row = []        for word in row:            if word not in stopwords:                new_row.append(word)        new_data.append(new_row)    return np.array(new_data)corpus = preprocess(X)print(corpus[42])

       

Building prefix dict from the default dictionary ...Dumping model to file cache /tmp/jieba.cacheLoading model cost 0.835 seconds.Prefix dict has been built successfully.

       

['跌停', '虽未', '打开', '交易', '已', '活跃', ' ', '基金', '市价', '估值', '云天化']

       In [5]

## 构建词表def build_vocab(data):    word2id = {}    vocab = Counter()    for row in data:        vocab.update(row)    vocab = sorted(vocab.items(), key=lambda x: x[1], reverse=True)    vocab = [('', 0)] + list(vocab) + [('', 0)]    word2id = {word[0]: i for i, word in enumerate(vocab)}    return word2iddef get_ids(data, word2id):    ids =  []    for row in data:        id_ = list(map(lambda x: word2id.get(x, word2id['']), row))        ids.append(id_)    return np.array(ids)def padding(data):    return Pad(pad_val=0)(data)word2id = build_vocab(corpus)ids = get_ids(corpus, word2id)padding_ids = padding(ids)print(padding_ids[42])print(padding_ids[56748])

       

[ 2181 80653  4283   170    37  1070     1    19 12830   879 29555     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0][ 1908  4439   319 25054   126  2642   329    13    20   213   231  6516     2     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0]

       In [6]

## 重写Datasetclass MyDataset(Dataset):    def __init__(self, X, Y):        super(MyDataset, self).__init__()        self.X = X        self.Y = Y    def __len__(self):        return self.X.shape[0]    def __getitem__(self, index):        return self.X[index], self.Y[index]

   In [7]

## 划分数据集————训练集、测试集、开发集def split(X, Y):    idx = [i for i in range(0, X.shape[0])]    np.random.shuffle(idx)    train_len = int(0.9 * len(idx))    return X[idx[:train_len]], Y[idx[:train_len]],            X[idx[train_len:]], Y[idx[train_len:]]train_X, train_Y, test_X, test_Y = split(padding_ids, Y)print("Train Set: ", train_X.shape, train_Y.shape)print("Test Set: ", test_X.shape, test_Y.shape)

       

Train Set:  (677227, 75) (677227,)Test Set:  (75248, 75) (75248,)

       

(三)模型搭建

In [8]

## 搭建模型class TextCNN(paddle.nn.Layer):    def __init__(self, vocab_size, embedding_size, classes, pretrained=None, kernel_num=100, kernel_size=[3, 4, 5], dropout=0.5):        super(TextCNN, self).__init__()        self.vocab_size = vocab_size        self.embedding_size = embedding_size        self.classes = classes        self.pretrained = pretrained        self.kernel_num = kernel_num        self.kernel_size = kernel_size        self.dropout = dropout        if self.pretrained != None:            self.embedding = nn.Embedding(num_embeddings=self.vocab_size, embedding_dim=self.embedding_size, padding_idx=0 ,_weight=pretrained)        else:            self.embedding = nn.Embedding(num_embeddings=self.vocab_size, embedding_dim=self.embedding_size, padding_idx=0)        self.convs = nn.LayerList([nn.Conv2D(1, self.kernel_num, (kernel_size_, embedding_size)) for kernel_size_ in self.kernel_size])        self.dropout = nn.Dropout(self.dropout)        self.linear = nn.Linear(3 * self.kernel_num, self.classes)    def forward(self, x):        embedding = self.embedding(x).unsqueeze(1)        convs = [nn.ReLU()(conv(embedding)).squeeze(3) for conv in self.convs]        pool_out = [nn.MaxPool1D(block.shape[2])(block).squeeze(2) for block in convs]        pool_out = paddle.concat(pool_out, 1)        logits = self.linear(pool_out)        return logits

   In [9]

## 训练配置BATCH_SIZE = 50EMBEDDING_SIZE = 150LEARNING_RATE = 0.00005EPOCHS = 5 # 5device = paddle.device.get_device()  #注意配置环境必须是GPU,否则以下训练程序将无法运行print(device)

       

gpu:0

       In [10]

## 模型训练与评估Train_Loader = DataLoader(MyDataset(paddle.to_tensor(train_X), paddle.to_tensor(train_Y)), batch_size=BATCH_SIZE, shuffle=True)Test_Loader = DataLoader(MyDataset(paddle.to_tensor(test_X), paddle.to_tensor(test_Y)), batch_size=BATCH_SIZE, shuffle=True)model = TextCNN(vocab_size=len(word2id), embedding_size=EMBEDDING_SIZE, classes=len(Y_dict))print(model)optimizer = optim.Adam(parameters=model.parameters(), learning_rate=LEARNING_RATE)criterion = nn.CrossEntropyLoss()for epoch in range(0, EPOCHS):    Train_Loss, Test_Loss = [], []    Train_Acc, Test_Acc = [], []    model.train()    for i, (x, y) in enumerate(Train_Loader):        x = x.cuda()        y = y.cuda()        pred = model(x)        loss = criterion(pred, y)        Train_Loss.append(loss.item())        Train_Acc.append(paddle.metric.accuracy(pred, y).numpy())        loss.backward()        optimizer.step()        optimizer.clear_grad()    model.eval()    for i, (x, y) in enumerate(Test_Loader):        x = x.cuda()        y = y.cuda()        pred = model(x)        Test_Loss.append(criterion(pred, y).item())        Test_Acc.append(paddle.metric.accuracy(pred, y).numpy())    print(        "Epoch: [{}/{}] TrainLoss/TestLoss: {:.4f}/{:.4f} TrainAcc/TestAcc: {:.4f}/{:.4f}".format(         epoch + 1, EPOCHS,         np.mean(Train_Loss), np.mean(Test_Loss),         np.mean(Train_Acc), np.mean(Test_Acc)         )     )

       

W0221 10:12:08.730477   101 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1W0221 10:12:08.736320   101 device_context.cc:465] device: 0, cuDNN Version: 7.6.

       

TextCNN(  (embedding): Embedding(249925, 150, padding_idx=0, sparse=False)  (convs): LayerList(    (0): Conv2D(1, 100, kernel_size=[3, 150], data_format=NCHW)    (1): Conv2D(1, 100, kernel_size=[4, 150], data_format=NCHW)    (2): Conv2D(1, 100, kernel_size=[5, 150], data_format=NCHW)  )  (dropout): Dropout(p=0.5, axis=None, mode=upscale_in_train)  (linear): Linear(in_features=300, out_features=14, dtype=float32))Epoch: [1/5] TrainLoss/TestLoss: 0.6914/0.3004 TrainAcc/TestAcc: 0.8045/0.9109Epoch: [2/5] TrainLoss/TestLoss: 0.2333/0.2359 TrainAcc/TestAcc: 0.9311/0.9292Epoch: [3/5] TrainLoss/TestLoss: 0.1707/0.2199 TrainAcc/TestAcc: 0.9486/0.9337Epoch: [4/5] TrainLoss/TestLoss: 0.1364/0.2162 TrainAcc/TestAcc: 0.9585/0.9347Epoch: [5/5] TrainLoss/TestLoss: 0.1125/0.2177 TrainAcc/TestAcc: 0.9657/0.9356

       In [11]

## 保存模型paddle.save(model.state_dict(), "TextCNN.pdparams")paddle.save(optimizer.state_dict(), "Adam.pdparams")

   

(四)预测数据与效果检测

In [12]

## 预测数据准备pred_X = pred_data['Sentence'].valuespred_corpus = preprocess(pred_X)pred_ids = get_ids(pred_corpus, word2id)pred_padding_ids = padding(pred_ids)print(pred_padding_ids.shape)## 预测过程,并将预测结果按照输入的训练集形式进行了保存Pred_Loader = DataLoader(MyDataset(paddle.to_tensor(pred_padding_ids), paddle.to_tensor(pred_padding_ids)), batch_size=BATCH_SIZE, shuffle=False)model.eval()pred_Y = []for i, (x, y) in enumerate(Pred_Loader):    x = x.cuda()    pred = model(x)    label = np.argmax(pred, axis=1)    pred_Y += list(label)## 可视化一些文本的预测结果pred_Name = [Y_dict[name] for name in pred_Y]MyPred = pd.DataFrame({'ClassNo': pred_Y, 'ClassName': pred_Name, 'Sentence': pred_X})print(MyPred.head())MyPred.to_csv('pred.csv', index=False)

       

(83599, 75)   ClassNo ClassName                 Sentence0        3        股票  北京君太百货璀璨秋色 满100省353020元1        5        教育        教育部:小学高年级将开始学习性知识2        6        科技    专业级单反相机 佳能7D单机售价9280元3        3        股票      星展银行起诉内地客户 银行强硬客户无奈4        3        股票   脱离中国的实际 强压RMB大幅升值只能是梦想

       

(五)封装功能 自定义文本输入

In [16]

model_params = paddle.load('TextCNN.pdparams')model_infer = TextCNN(vocab_size=len(word2id), embedding_size=EMBEDDING_SIZE, classes=len(Y_dict))model_infer.set_state_dict(model_params)sentence = input()infer_corpus = preprocess([sentence])infer_ids = get_ids(infer_corpus, word2id)infer_padding_ids = padding(infer_ids)model_infer.eval()val = model_infer(paddle.to_tensor(infer_padding_ids))label = np.argmax(val, axis=1)[0]print("Sentence: ", sentence, " label: ", Y_dict[label])

       

Sentence:  再次点球失手!如何评价梅西现在的踢球水平?  label:  体育

       

以上就是【AI达人创造营第二期】一文读懂textCNN模型原理的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/50386.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
windows 10 如何设置开始菜单全屏幕?windows 10开始菜单全屏幕设置方法
上一篇 2025年11月8日 16:45:42
Win7系统开机出现系统错误ActiveDetect32.dll丢失的解决方法
下一篇 2025年11月8日 16:47:37

相关推荐

  • 开源免费PHP工具 PHP开发效率提升利器

    推荐开源免费PHP开发工具以提升效率:VS Code、Sublime Text轻量高效,PhpStorm专业强大;调试用Xdebug、Kint、Ray;依赖管理选Composer;代码质量工具包括PHPStan、Psalm、PHP_CodeSniffer;数据库管理可用%ignore_a_1%MyA…

    2026年5月10日
    000
  • Matplotlib 地图中多类型图例的创建与优化

    Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化

    本教程旨在解决matplotlib地图可视化中,如何在一个图例中同时展示颜色块(如区域分类)和自定义标记(如特定兴趣点)的问题。文章详细介绍了当传统`patch`对象无法正确显示标记时,如何利用`matplotlib.lines.line2d`创建标记图例句柄,并将其与颜色块图例句柄合并,从而生成一…

    2026年5月10日 用户投稿
    100
  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • RichHandler与Rich Progress集成:解决显示冲突的教程

    在使用rich库的`richhandler`进行日志输出并同时使用`progress`组件时,可能会遇到显示错乱或溢出问题。这通常是由于为`richhandler`和`progress`分别创建了独立的`console`实例导致的。解决方案是确保日志处理器和进度条组件共享同一个`console`实例…

    2026年5月10日
    000
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    000
  • 创建指定大小并填充特定数据的Golang文件教程

    本文将介绍如何使用Golang创建一个指定大小的文件,并用特定数据填充它。我们将使用 `os` 包提供的函数来创建和截断文件,从而实现快速生成大文件的目的。示例代码展示了如何创建一个10MB的文件,并将其填充为全零数据。掌握这些方法,可以方便地在例如日志系统或磁盘队列等场景中,预先创建测试文件或初始…

    2026年5月10日
    000
  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • 如何插入查询结果数据_SQL插入Select查询结果方法

    如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法

    使用INSERT INTO…SELECT语句可高效插入数据,通过NOT EXISTS、LEFT JOIN、MERGE语句或唯一约束避免重复;表结构不一致时可通过别名、类型转换、默认值或计算字段处理;结合存储过程可提升可维护性,支持参数化与动态SQL。 将查询结果数据插入到另一个表中,可以…

    2026年5月10日 用户投稿
    000
  • 使用 WebCodecs VideoDecoder 实现精确逐帧回退

    本文档旨在解决在使用 WebCodecs VideoDecoder 进行视频解码时,实现精确逐帧回退的问题。通过比较帧的时间戳与目标帧的时间戳,可以避免渲染中间帧,从而提高用户体验。本文将提供详细的解决方案和示例代码,帮助开发者实现精确的视频帧控制。 在使用 WebCodecs VideoDecod…

    2026年5月10日
    000
  • Discord.py 交互按钮超时与持久化解决方案

    本教程旨在解决Discord.py中交互按钮在一段时间后出现“This Interaction Failed”错误的问题。我们将深入探讨视图(View)的超时机制,并提供通过正确设置timeout参数以及利用bot.add_view()方法实现按钮持久化的具体方案,确保您的机器人交互功能稳定可靠,即…

    2026年5月10日
    000
  • Debian Copilot的社区活跃度如何

    debian copilot是codeberg社区维护的ai助手,旨在为debian用户提供服务。尽管搜索结果中没有直接提供关于debian copilot社区支持活跃度的具体数据,但我们可以通过debian社区的整体活跃度和特点来推断其活跃性。 Debian社区的一般情况: Debian拥有详尽的…

    2026年5月10日
    000
  • JavaScript 动态菜单点击高亮效果实现教程

    本教程详细介绍了如何使用 JavaScript 实现动态菜单的点击高亮功能。通过事件委托和状态管理,当用户点击菜单项时,被点击项会高亮显示(绿色),同时其他菜单项恢复默认样式(白色)。这种方法避免了不必要的DOM操作,提高了性能和代码可维护性,确保了无论点击方向如何,功能都能稳定运行。 动态菜单高亮…

    2026年5月10日
    200
  • c++如何实现UDP通信_c++基于UDP的网络通信示例

    UDP通信基于套接字实现,适用于实时性要求高的场景。1. 流程包括创建套接字、绑定地址(接收方)、发送(sendto)与接收(recvfrom)数据、关闭套接字;2. 服务端监听指定端口,接收客户端消息并回传;3. 客户端发送消息至服务端并接收响应;4. 跨平台需处理Winsock初始化与库链接,编…

    2026年5月10日
    000
  • html5怎么画实线_HTML5用CSS border-style:solid画元素实线边框【绘制】

    可通过CSS的border-style属性设为solid添加实线边框:一、内联样式用border:2px solid #000;二、内部样式表统一设置如div{border:1px solid #333};三、外部CSS文件定义.my-box{border:3px solid red}并引入;四、单…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信