天池NLP学习赛(5)基于深度学习的文本分类2(word2vec与TextCNN实现文本分类)

基于深度学习的文本分类2

主要内容是从datawhale的官方学习blog中得到的,网址,主要介绍了相关模型的网络结构和模型的训练过程

分为两部分:
(1)word2vec词嵌入(词向量)
(2)利用神经网络在词向量的基础上实现文本分类(主要是TextCNN,因为TextRNN只用换个网络结构,然后HAN(分层注意力网络)的论文暂时咕咕咕了)希望以后有一天能仔细看看!

相当于利用word2vec模型作为embedding layer。正常的操作是用现有的所有文本(或者可以利用其它大量相似语料)进行word2vec的模型训练,得到词与词之间的联系作为词的特征。

这里的内容是python的实现和一些细节介绍。就简单例子,具体操作(因为的实战代码长且慢就没放上去)

part 1:文本表示方法 3:word2vec

(一) 主要内容

介绍:Word2vec模型为浅而双层的神经网络,网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模型假设下,词的顺序是不重要的。训练完成之后,word2vec模型可用来映射每个词到一个向量,可用来表示词对词之间的关系,该向量为神经网络之隐藏层。

word2vec的主要思路:通过单词和上下文彼此预测,对应的两个算法分别为:

(1)Skip-grams (SG):给定input word来预测上下文

(2)Continuous Bag of Words (CBOW):给定上下文,来预测input word

模型本质上是通过样本计算一个词a的一定范围内(例如前后的词)出现词b的概率。
Word2Vec模型实际上分为了两个部分,第一部分为建立模型(架构模型,训练参数),第二部分是通过模型获取嵌入词向量(input → \rightarrow output)。

另外提出两种更加高效的训练方法:

(1)Hierarchical softmax(之前fasttext模型的论文中提到过论文地址)

(2)Negative sampling

(二)word2vec例子

在这里我们具体介绍word2vec模型的实现,模型的结构和具体过程参考:

(1)使用gensim库

这里使用gensim库来实现word2vec,anaconda直接pip install gensim。

(2)word2vec API
class gensim.models.word2vec.Word2Vec(sentences=None, size=100, alpha=0.025, window=5, min_count=5, max_vocab_size=None, sample=0.001, seed=1, workers=3, min_alpha=0.0001, sg=0, hs=0, negative=5, cbow_mean=1, hashfxn=<built-in function hash>, iter=5, null_word=0, trim_rule=None, sorted_vocab=1, batch_words=10000)

参数介绍:
(1)sentences:输入语句:形式为[‘I’,‘am’,‘a’,‘vegetable’,‘dog’]

(2)size:特征向量的维度

(3)alpha: 在随机梯度下降法中的初始学习率(初始步长)

(4)window:描述滑动窗口大小,表示在一个句子中,当前单词和被预测的单词之间的最大距离看这里的图示介绍

一个例子:
window=2时:
对句子:[‘I’,‘am’,‘a’,‘vegetable’,‘dog’]选定包括’a’的前两个词和’a’的后两个词组成的窗口, 滑动窗口进行模型训练:
\quad (a)在Skip-grams时,输入’a’,根据’am’‘vegetable’‘dog’,(一共有100个单词,我们训练这100个词和’a’的相关性)
\quad (b)在CBOW时,输入’am’‘vegetable’‘dog’,根据’a’,训练所有100个单词和’am’‘vegetable’'dog’的相关性

(5)min_count:最小词频,忽略所有总频率低于此频率的单词。

(6)max_vocab_size 用于限制在构建单词表过程使用的内存,如果出现比这个数多的不同单词,就修剪掉频率最小的那些单 词;每100million单词类型需要1GB的RAM,设置为None即没有限制(默认)

(7)sample : 配置高频词被随机下采样的阈值,比较可靠的范围是(0,1e-5)

主要的原因是word2vec模型在训练时会出现’a’,'the’这样的高频词,这样的高频词和其它词之间的联系不能带 来很大的信息,从而对出现高频词的词对(‘the’,‘dog’/‘book’/…)进行抽样训练
保留某个单词的概率: P ( x ) = ( F ( x ) 0.001 + 1 ) × 0.001 F ( x ) P(x)=(\sqrt{\frac{F(x)}{0.001}+1})\times \frac{0.001}{F(x)} P(x)=(0.001F(x)+1 )×F(x)0.001

(8)seed:随机种子

(9)workers:用于训练模型的线程

(10)min_alpha: 最小的迭代步长值。随着训练的进行,学习率将线性下降到"min_alpha"

(11)sg : 训练模型: 1表示skip-gram; 0表示CBOW

(12)hs & negative : 模型训练方式
\quad hs :如果为1, 将用hierarchical softmax 训练模型
(hierarchical softmax用霍夫曼树来代替从隐藏层到输出softmax层的映射,用以避免计算所有的softmax,具体见开头 blog)
\quad hs :如果为0, 并且negative不为0,则将采样负采样训练模型
(负采样是因为单词在one-hot 编码后所占空间较大例如’dog’=[0,1,…,0,0,0,…,0] ∈ 0 , 1 n \in {0,1}^n 0,1n,假设此时输入’vegetable’输出为’dog’,dog的编码中1在第2个位置,再抽取m个位置的位置,对’vegetable’周围可能出现n种单词的概率 P ∈ R n P\in R^n PRn中m+1个位置的值进行权重更新)具体见文章开头blog中内容
\quad negative :如果大于零负采样将要被用于训练
这个负整数指定多少噪音单词被绘制,默认为5,如果设为0,不使用负采样;
PS: 在论文中,作者指出指出对于小规模数据集,选择5-20个negative words会比较好,对于大规模数据集可以仅选择2-5个negative words。

(13)cbow_mean : {0, 1}如果为0, 在cbow做投影的时候则使用上下文词向量的总和. 如果为1, 则使用平均值, 仅在使用cbow时适用.

具体意思就是根据上下文m个词向量与所有n个向量的关系概率矩阵: R n × m R^{n\times m} Rn×m得到所有n个向量出现在这m个词中间的概率 R n R^n Rn时的计算方法是每行求和还是求平均

(14)hashfxn : function,哈希函数用于随机初始化权重,以提高训练的可重复性。

(15) iter : 语料库上的迭代次数,默认是5。对于大语料,可以增大这个值。

(16)trim_rule : function,词汇修剪规则,指定是否应保留某些单词,对其进行修剪或使用默认值处理

(17)sorted_vocab:{0,1}, 如果为1,则在分配单词索引之前,按降序对词汇表进行排序。
参见:〜gensim.models.word2vec.Word2VecVocab.sort_vocab()方法

(18) batch_words传递给工作线程(以及cython例程)的示例批处理的目标大小(以字为单位)。

(如果单个文本的长度超过10000个单词,则将传递较大的批处理,但是标准cython代码将截断到该最大值)。

(3)训练集文本处理与模型训练

一般的操作过程参考:

1)将语料库预处理:一行一个文档或句子,将文档或句子分词(以空格分割,英文可以不用分词,英文单词之间已经由空格分割,中文预料需要使用分词工具进行分词,常见的分词工具有StandNLP、ICTCLAS、Ansj、FudanNLP、HanLP、结巴分词等);

2)将原始的训练语料转化成一个sentence的迭代器,每一次迭代返回的sentence是一个word(utf8格式)的列表。可以使用Gensim中word2vec.py中的LineSentence()方法实现;
PS:因为一般用于训练的语素集过大,需要迭代器减少存储。特别小的训练集也可以不用迭代器

3)将上面处理的结果输入Gensim内建的word2vec对象进行训练即可:

原文件chin_eg.txt:
我是菜狗,但不爱吃菜。
菜狗不是狗吗?
狗狗真可爱。
我觉得狗真可爱。
狗觉得你可爱吗?

from gensim.models import Word2Vec #Word2Vec在word2vec中
from gensim.models import word2vec
import jieba
file= 'chin_eg.txt'
# 先用jieba对中文语料分词
f1= open(file, 'r', encoding='UTF-8')
f2 = f1.read()
f3 = jieba.cut(f2)
f5 = open('fenci.txt', 'w', encoding='UTF-8')
f5.write(' '.join(f3))

得到’fenci,txt’:
我 是 菜 狗 , 但 不 爱 吃 菜 。
菜狗 不是 狗 吗 ?
狗狗 真 可爱 。
我 觉得 狗 真 可爱 。
狗 觉得 你 可爱 吗 ?

#使用LineSentence分句,并得到迭代器 ps:还可以人工手动用写迭代器类(用yield啥的...令人头秃)

#f4=  word2vec.Text8Corpus('fenci.txt')  #Text8Corpus最后得到的是一整个文本
f4=  word2vec.LineSentence('fenci.txt')  #LineSentence则是把文本按换行分成句子
#如果是Text8Corpus:
for i in f4:print(i)
['我', '是', '菜', '狗', ',', '但', '不', '爱', '吃', '菜', '。', '菜狗', '不是', '狗', '吗', '?', '狗狗', '真', '可爱', '。', '我', '觉得', '狗', '真', '可爱', '。', '狗', '觉得', '你', '可爱', '吗', '?']
#如果是LineSentence:
for i in f4:print(i)
['我', '是', '菜', '狗', ',', '但', '不', '爱', '吃', '菜', '。']
['菜狗', '不是', '狗', '吗', '?']
['狗狗', '真', '可爱', '。']
['我', '觉得', '狗', '真', '可爱', '。']
['狗', '觉得', '你', '可爱', '吗', '?']

关于lineSentence方法:
lines = gensim.models.word2vec.LineSentence(filename, max_sentence_length=10, limit=3)
参数:max_sentence_length是返回的每句话中元素的最大个数,limit=3是说读取sample_text.txt中的前三行。

#构建词向量模型
w2v_model = Word2Vec(f4, size=10,window=2, min_count=0) 
(4)模型查看与使用
#模型存放与加载
w2v_model.save('w2v') 
w2v_model = Word2Vec.load('w2v') 
#与'我'和'狗'最相关,但与'菜'最无关
w2v_model.most_similar(positive=['我', '狗'], negative=['菜']) 
[('爱', 0.45055341720581055),
 ('吃', 0.29538390040397644),
 ('狗狗', 0.21414856612682343),
 (',', 0.21213683485984802),
 ('。', 0.09701236337423325),
 ('?', 0.0072501301765441895),
 ('但', -0.016102807596325874),
 ('可爱', -0.0910077691078186),
 ('不是', -0.1033945083618164),
 ('吗', -0.14775775372982025)]
#计算相似度
w2v_model.similarity('狗', '我') 
0.43826625
#和所有其它词的相关性矩阵
w2v_model['我']
array([ 0.02918558, -0.03668086,  0.01387162,  0.00700803, -0.0136869 ,
       -0.01909925, -0.00430217,  0.00719638, -0.02625507,  0.00987847],
      dtype=float32)
#size
w2v_model.layer1_size
10
#获取model中的词:
#gensim 1.0.0 以前的版本 用model.vocab
#gensim 1.0之后的版本用model.wv.vocab
w2v_model.wv.vocab
{'我': <gensim.models.keyedvectors.Vocab at 0x2a75353f4c8>,
 '是': <gensim.models.keyedvectors.Vocab at 0x2a75353f148>,
 '菜': <gensim.models.keyedvectors.Vocab at 0x2a75353f308>,
 '狗': <gensim.models.keyedvectors.Vocab at 0x2a75353fe88>,
 ',': <gensim.models.keyedvectors.Vocab at 0x2a75353f248>,
 '但': <gensim.models.keyedvectors.Vocab at 0x2a75353fb48>,
 '不': <gensim.models.keyedvectors.Vocab at 0x2a75353f0c8>,
 '爱': <gensim.models.keyedvectors.Vocab at 0x2a75353f688>,
 '吃': <gensim.models.keyedvectors.Vocab at 0x2a75353fc08>,
 '。': <gensim.models.keyedvectors.Vocab at 0x2a75353f5c8>,
 '菜狗': <gensim.models.keyedvectors.Vocab at 0x2a75353fd88>,
 '不是': <gensim.models.keyedvectors.Vocab at 0x2a75353f808>,
 '吗': <gensim.models.keyedvectors.Vocab at 0x2a75353f348>,
 '?': <gensim.models.keyedvectors.Vocab at 0x2a75353f408>,
 '狗狗': <gensim.models.keyedvectors.Vocab at 0x2a75353f508>,
 '真': <gensim.models.keyedvectors.Vocab at 0x2a75353f948>,
 '可爱': <gensim.models.keyedvectors.Vocab at 0x2a75353f888>,
 '觉得': <gensim.models.keyedvectors.Vocab at 0x2a75353f8c8>,
 '你': <gensim.models.keyedvectors.Vocab at 0x2a75353fc48>}

part 2:TextCNN

TextCNN就是输入为文本的CNN
结构:
在这里插入图片描述

关于CNN见这篇blog里面的链接

(一)利用训练好的word2vec模型嵌入训练集

主要的内容包括:
(1)构造嵌入时的权重矩阵
(2)把输入的文字转化为数字
(3)进行模型训练

训练集按照word2vec训练集一样的方式转化为text_x的格式

训练集:
“我 狗 可爱 吗” lable=1
“我 爱 狗” lable=1
“狗狗 不是 狗” lable=2

预测集: “我 不 爱 狗”

test=[['我','狗','可爱' ,'吗'],
      ['我','爱','狗','?'],
      ['狗狗','不是','狗'],
     ['我','不','爱','狗']]
(1) 先构造一个字典来表示每个词与对应的词向量

借鉴

#提取word2vec模型中所有的word
words = [word for word, Vocab in w2v_model.wv.vocab.items()]
words
['我',
 '是',
 '菜',
 '狗',
 ',',
 '但',
 '不',
 '爱',
 '吃',
 '。',
 '菜狗',
 '不是',
 '吗',
 '?',
 '狗狗',
 '真',
 '可爱',
 '觉得',
 '你']
def get_word2vec_dictionaries(words=words,size=10, model=w2v_model):
    Word2VecModel =model
    word_index = {" ": 0}# 初始化 `[word : token]` ,后期 tokenize 语料库就是用该词典。
    word_vector = {} # 初始化`[word : vector]`字典
    
    # 初始化存储所有向量的大矩阵,留意其中多一位(首行),词向量全为 0,用于 padding补零。
    # 行数为所有单词数+1 比如 10000+1 ; 列数为 词向量“维度”比如10。
    embeddings_matrix = np.zeros((len(words) + 1,size))

    ## 填充 上述 的字典 和 大矩阵
    for i in range(len(words)):
        word = words[i]  # 每个词语
        word_index[word] = i + 1  # 词语:序号
        word_vector[word] = Word2VecModel[word] # 词语:词向量
        embeddings_matrix[i + 1] = Word2VecModel[word]  # 词向量矩阵

    return word_index, word_vector, embeddings_matrix
embeddings_matrix
array([[ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ,
         0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.02918558, -0.03668086,  0.01387162,  0.00700803, -0.0136869 ,
        -0.01909925, -0.00430217,  0.00719638, -0.02625507,  0.00987847],
       [-0.02459667,  0.04121378, -0.00013759, -0.00741298, -0.01256216,
        -0.01028162,  0.03575801, -0.04929112,  0.03099362,  0.02482377],
       [-0.01472408,  0.01241681,  0.04788949,  0.04490589,  0.00694828,
        -0.02728049,  0.01801089,  0.01510288, -0.0139395 , -0.01220352],
       [-0.01763814, -0.03368247,  0.02202123,  0.03008921,  0.00085382,
        -0.00170778,  0.03796937,  0.03139202, -0.02336897,  0.02523298],
       [-0.00505908,  0.013406  ,  0.03043254,  0.03008946, -0.04977243,
        -0.02822685,  0.03945045,  0.04044256,  0.00988977,  0.04591493],
       [-0.03774097, -0.01927538, -0.01066185, -0.01081436, -0.02101368,
        -0.0287521 ,  0.01786302, -0.00663138, -0.00847355, -0.03390852],
       [ 0.00835856,  0.02185489,  0.02293554,  0.01775109,  0.04160322,
         0.01155878, -0.03639844,  0.03596485, -0.02243769, -0.00929452],
       [-0.00310476, -0.0406886 ,  0.03530734, -0.00711615, -0.01292462,
        -0.02054859,  0.00845748,  0.00597784,  0.02351156,  0.01597429],
       [ 0.01225774, -0.03059088, -0.02975468, -0.00247338, -0.03355996,
        -0.03004243,  0.03761639, -0.03024273,  0.00282844, -0.01827502],
       [-0.0203339 ,  0.01015598,  0.03256533, -0.04872689,  0.04996153,
        -0.0191166 ,  0.01909535,  0.02980656, -0.04201154,  0.02475672],
       [-0.0401343 , -0.00464759, -0.0400188 ,  0.01978544,  0.01567098,
        -0.01352168,  0.01821931,  0.02507673,  0.01642727, -0.04031501],
       [-0.00378749, -0.01765673, -0.01972143,  0.03622149, -0.0221294 ,
        -0.02966275, -0.03071216,  0.04681642,  0.04822319, -0.03892935],
       [ 0.01448885,  0.02136381, -0.02702899,  0.03764353,  0.03078468,
         0.04216314, -0.01026488, -0.03162862, -0.02188382,  0.01204589],
       [-0.04894356, -0.02543556, -0.03540323, -0.02111313,  0.03878152,
        -0.01002491, -0.02153409,  0.01190527,  0.01867069,  0.01467802],
       [ 0.01772207,  0.00661998, -0.0244507 , -0.024116  ,  0.03875529,
        -0.04017496, -0.02940588,  0.00625848, -0.02173358,  0.04775837],
       [ 0.03712008,  0.00605327,  0.03258163,  0.03730477,  0.00342061,
        -0.00654243,  0.01591756, -0.00345628,  0.0383717 , -0.00104739],
       [-0.04687626, -0.00401429,  0.02733486,  0.04723512, -0.03447558,
         0.04926655, -0.02872569, -0.00924688,  0.03859049,  0.03825805],
       [ 0.00338666,  0.02183441,  0.0260055 , -0.03242844,  0.01665515,
        -0.00131409, -0.03630874, -0.04660666,  0.00281902, -0.03756275],
       [ 0.01810994,  0.04110958, -0.01070155, -0.01099044,  0.01722193,
         0.00750162,  0.03553517, -0.03988532, -0.02057942, -0.0451868 ]])
(2)把input的文字变为数字

根据词语在word_index上的号码进行编码

test_x=test[:3]
test_x
[['我', '狗', '可爱', '吗'], ['我', '爱', '狗', '?'], ['狗狗', '不是', '狗']]
import keras
def tokenizer(texts, word_index):
    data = []
    for sentence in texts:
        new_txt = []
        for word in sentence:
            try:
                new_txt.append(word_index[word])  # 把句子中的 词语转化为index
            except:
                new_txt.append(0)
        data.append(new_txt)

    texts =keras.preprocessing.sequence.pad_sequences(data)  # 使用keras的内置函数padding对齐句子,好处是输出numpy数组,不用自己转化了
    return texts
texts=tokenizer(texts=test_x, word_index=word_index)
texts
array([[ 1,  4, 17, 13],
       [ 1,  8,  4, 14],
       [ 0, 15, 12,  4]])
(4)带入模型
import tensorflow as tf

关于嵌入层的参数设置:

#这里只是一个说明,对于上述例子的具体实现看下面一个cell
embedding_layer = Embedding(input_dim=len(embeddings_matrix),  # 字典长度
                                output_dim = EMBEDDING_LEN,  # 词向量 长度(25)
                                weights=[embeddings_matrix],  # 重点:预训练的词向量系数
                                input_length=MAX_SEQUENCE_LENGTH,  # 每句话的 最大长度(必须                                       padding)
                                trainable=False,  # 是否在 训练的过程中 更新词向量
                                name= 'embedding_layer'
                                )

model = tf.keras.models.Sequential([
    tf.keras.layers.Embedding(input_dim=len(embeddings_matrix),
                              output_dim =size,input_length=len(texts[0]),weights=[embeddings_matrix],trainable=False),
    tf.keras.layers.Conv1D(8, 2, padding='same',activation='relu',input_shape=input_shape),#8是特征数,2是一维kernel长度
    tf.keras.layers.MaxPool1D(2),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(2)# lable有2种
])
model.compile(optimizer='adam',
              loss='categorical_crossentropy',#其实二分类应该是binary_crossentropy来着,多分类才是这个
              metrics=['accuracy'])
model.summary()
Model: "sequential_9"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_7 (Embedding)      (None, 4, 10)             200       
_________________________________________________________________
conv1d_4 (Conv1D)            (None, 4, 8)              168       
_________________________________________________________________
max_pooling1d_4 (MaxPooling1 (None, 2, 8)              0         
_________________________________________________________________
flatten_9 (Flatten)          (None, 16)                0         
_________________________________________________________________
dense_9 (Dense)              (None, 2)                 34        
=================================================================
Total params: 402
Trainable params: 202
Non-trainable params: 200
_________________________________________________________________
(5)把lable编码,进行模型测试
#这个例子中1,2句lable=1,第3句lable=2
model.fit(texts,[[[1,0],[1,0],[0,1]]],batch_size=3,epochs=2)
Epoch 1/2
3/3 [==============================] - 0s 26ms/sample - loss: 0.7830 - acc: 0.6667
Epoch 2/2
3/3 [==============================] - 0s 997us/sample - loss: 0.7431 - acc: 0.6667

<tensorflow.python.keras.callbacks.History at 0x2a80dc4e9c8>
pre_x=tokenizer(texts=test[3], word_index=word_index)
pre_x
array([[1],
       [7],
       [8],
       [4]])
pre_x=pre_x.reshape(1,4)
pre_x
array([[1, 7, 8, 4]])
model.predict(pre_x)#得到的第二项最大,所以lable=2
array([[-0.03471019, -0.01787856]], dtype=float32)

part 3:TextRNN

和CNN的类似,就搭的网络不一样就不写例子辽!具体的结构还是看之前那个blog的最后

part 4:HAN (Hierarchical Attention Network )

Hierarchical Attention Network for Document Classification论文原文其它一些参考
基于层级注意力,在单词和句子级别分别编码并基于注意力获得文档的表示,然后经过Softmax进行分类。其中word encoder的作用是获得句子的表示,可以替换为上节提到的TextCNN和TextRNN,也可以替换为下节中的BERT。

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
基于深度学习文本分类任务是指利用深度学习模型对文本进行情感分类。在这个任务中,我们使用了CNN和RNN模型来进行文本分类。数据集包含了15万余项英文文本,情感分为0-4共五类情感。任务的流程如下:输入数据→特征提取→神经网络设计→结果输出。 在特征提取阶段,我们使用了词嵌入(Word embedding)技术。词嵌入是一种将单词映射到低维向量空间的方法,它可以将单词的语义信息编码为向量表示。在本次任务中,我们参考了博客\[NLP-Beginner 任务二:基于深度学习文本分类\](https://pytorch.org/Convolutional Neural Networks for Sentence Classification)中的方法,使用了预训练的词嵌入模型。 神经网络设计阶段,我们采用了卷积神经网络(CNN)和循环神经网络(RNN)的结合。具体来说,我们使用了四个卷积核,大小分别为2×d, 3×d, 4×d, 5×d。这样设计的目的是为了挖掘词组的特征。例如,2×d的卷积核用于挖掘两个连续单词之间的关系。在模型中,2×d的卷积核用红色框表示,3×d的卷积核用黄色框表示。 最后,我们将模型的输出结果进行分类,得到文本的情感分类结果。这个任务的目标是通过深度学习模型对文本进行情感分类,以便更好地理解和分析文本数据。 #### 引用[.reference_title] - *1* *3* [NLP-Brginner 任务二:基于深度学习文本分类](https://blog.csdn.net/m0_61688615/article/details/128713638)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [NLP基本任务二:基于深度学习文本分类](https://blog.csdn.net/Mr_green_bean/article/details/90480918)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值