当前位置: 首页 > article >正文

词嵌入(Word Embedding)之Word2Vec、GloVe、FastText

简介:个人学习分享,如有错误,欢迎批评指正。

词嵌入(Word Embedding)是一种将词语映射到低维稠密向量空间的技术,能够捕捉词与词之间的语义关系。Word2Vec、GloVe、FastText 是常见的词嵌入方法,它们各自有不同的原理和特点。

一、Word2Vec

Word2Vec是Google在2013年提出的一种词嵌入(Word Embedding)模型,其核心思想是将词语映射到一个连续的低维向量空间,使得语义相似的词在向量空间中距离更近。通过这种方式,词语的语义关系可以用向量之间的数学运算(如余弦相似度)来度量。

1.基本原理

Word2Vec 的核心思想是基于 分布式假设,即“上下文相似的词语具有相似的语义”。通过大量语料库的训练,Word2Vec 学习到每个词语的向量表示,使得这些向量能够捕捉词语之间的语义关系。

Word2Vec 主要有两种模型架构

  1. Continuous Bag-of-Words (CBOW) 模型:
  • 目标: 根据上下文预测中心词。
  • 原理: 将上下文词向量求和或平均,输入到神经网络,预测中心词的概率分布
  • 特点: 适合小型数据集,训练速度较快。
  1. Skip-Gram 模型:
  • 目标: 根据中心词预测上下文词。
  • 原理: 输入中心词的向量,通过神经网络,预测其周围上下文词的概率分布
  • 特点: 在大型数据集上表现更好,能够捕捉更多的稀有词信息。

向量性质和语义关系

Word2Vec 生成的词向量具有以下特点:

  1. 相似性捕捉: 语义相似的词语,其向量在空间中距离较近。

  2. 线性关系: 词向量之间的差异可以反映某些语义关系。 例如:

王国 ⃗ − 男人 ⃗ + 女人 ⃗ ≈ 王后 ⃗ \vec{王国} - \vec{男人} + \vec{女人} \approx \vec{王后} 王国 男人 +女人 王后

  1. 聚类效果: 同一类别的词语在向量空间中往往形成聚类。

2.模型结构

  1. CBOW 模型结构
  • 输入层: 上下文词的one-hot 向量表示。
  • 投影层: 将one-hot 向量映射到低维嵌入空间,通常使用嵌入矩阵。
  • 隐藏层: 将上下文词的嵌入向量进行平均求和
  • 输出层: 通过 softmax 函数,输出中心词的概率分布

数学公式:

给定上下文词 w c o n t e x t w_{context} wcontext,目标是最大化中心词 w t a r g e t w_{target} wtarget的条件概率:

P ( w t a r g e t ∣ w c o n t e x t ) = s o f t m a x ( v w t a r g e t T h ) P(w_{target} \mid w_{context}) = softmax(v_{w_{target}}^T h) P(wtargetwcontext)=softmax(vwtargetTh)

其中, h h h 是上下文词向量的平均值, v w t a r g e t v_{w_{target}} vwtarget 是中心词的输出向量。

  1. Skip-Gram 模型结构
  • 输入层: 中心词的 one-hot 向量表示。
  • 投影层: 将中心词的 one-hot 向量映射到嵌入空间
  • 输出层: 通过 softmax 函数,预测上下文词的概率分布

数学公式:

给定中心词 w t a r g e t w_{target} wtarget,目标是最大化其上下文词 w c o n t e x t w_{context} wcontext的条件概率:

P ( w c o n t e x t ∣ w t a r g e t ) = s o f t m a x ( v w c o n t e x t T h ) P(w_{context} \mid w_{target}) = softmax(v_{w_{context}}^T h) P(wcontextwtarget)=softmax(vwcontextTh)

其中, h h h 是中心词的嵌入向量, v w c o n t e x t v_{w_{context}} vwcontext 是上下文词的输出向量。

3.训练方法和实践步骤

3.1.训练方法

由于词汇表通常非常大,直接计算 softmax 的代价过高。为此,Word2Vec 引入了两种高效的近似训练方法:

a.负采样 (Negative Sampling)

  • 思想: 只更新一小部分负样本的参数,而非整个词汇表。
  • 方法: 对于每个正样本(真实的词对),随机采样 k 个负样本(无关的词对),使模型区分正负样本。

负采样的基本原理
负采样通过简化优化目标,减少计算量。它的核心思想是:与其每次计算所有类别的softmax分布,不如仅针对正样本和少量负样本进行计算。这些负样本通过随机采样获得,而正样本是实际存在于数据中的正确标签。

具体步骤如下:

  • 正样本(Positive Sample):对于每个输入词语,模型会选择其上下文中的正确词语作为正样本。
  • 负样本(Negative
    Samples):为了降低计算量,模型随机选择若干个错误的词语作为负样本。负样本来自词汇表中的其他词语,通常是无关词。
  • 优化目标:模型不再优化整个词汇表的softmax概率分布,而是仅仅优化正样本与若干负样本的相对概率。

负采样数学表述

在传统的 Skip-Gram 模型中,目标是最大化每对词之间的共现概率:

P ( Context Word ∣ Target Word ) = e v c ⋅ v w ∑ w ′ ∈ V e v c ⋅ v w ′ P(\text{Context Word}|\text{Target Word}) = \frac{e^{v_c \cdot v_w}}{\sum_{w' \in V} e^{v_c \cdot v_{w'}}} P(Context WordTarget Word)=wVevcvwevcvw

其中 v c v_c vc v w v_w vw 分别表示上下文词和目标词的词向量, V V V 是词汇表。

负采样优化目标如下:

L = log ⁡ σ ( v c ⋅ v w ) + ∑ i = 1 k log ⁡ σ ( − v c ⋅ v n i ) L = \log \sigma(v_c \cdot v_w) + \sum_{i=1}^{k} \log \sigma(-v_c \cdot v_{n_i}) L=logσ(vcvw)+i=1klogσ(vcvni)

其中:

  • σ ( x ) \sigma(x) σ(x) 是 sigmoid 函数,用于将输出限制在 (0,1) 之间。
  • v n i v_{n_i} vni 是随机采样得到的负样本词向量。
  • k k k 是负采样的样本数量,通常取 5 到 20 之间。

b.层次化 Softmax (Hierarchical Softmax)

  • 思想: 将 softmax 分解为二叉树的形式,降低计算复杂度。
  • 方法: 将词汇表组织成霍夫曼编码的二叉树,预测路径上的二元决策。

3.2.实践步骤

  1. 语料预处理
  • 分词: 将文本切分为单词序列。
  • 去除停用词: 可根据需求去除常见但信息量低的词语。
  • 建立词汇表: 统计词频,建立词语索引的映射关系。
  1. 模型训练
  • 选择模型架构: CBOW 或 Skip-Gram。
  • 设定超参数: 嵌入维度、窗口大小、负采样数量、学习率等。
  • 训练参数: 使用优化算法(如 SGD)更新参数。
  1. 模型评估
  • 相似度测试: 计算词向量之间的余弦相似度,验证相似词是否接近。
  • 下游任务验证: 将词向量应用于具体任务,评估性能提升。

4.python代码实现

from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence

# 1. 加载语料
# 假设语料文件为 'corpus.txt',每行一个经过分词的句子,词语用空格分隔
sentences = LineSentence('corpus.txt')

# 2. 训练Word2Vec模型
model = Word2Vec(
    sentences,
    vector_size=100,   # 词向量的维度
    window=5,          # 上下文窗口大小
    min_count=5,       # 词频低于min_count的词将被忽略
    workers=4,         # 使用4个线程进行训练
    sg=1,              # 使用Skip-Gram模型;若为0,则使用CBOW模型
    negative=5,        # 负采样个数
    sample=1e-3,       # 下采样率
    epochs=5           # 迭代次数
)

# 3. 保存模型
model.save('word2vec.model')

# 4. 加载模型
model = Word2Vec.load('word2vec.model')

# 5. 使用模型

# 获取词向量
vector = model.wv['苹果']
print('苹果的词向量:')
print(vector)

# 计算两个词的相似度
similarity = model.wv.similarity('苹果', '香蕉')
print(f'苹果和香蕉的相似度:{similarity}')

# 找出与某个词最相似的词
similar_words = model.wv.most_similar('苹果', topn=5)
print('与苹果最相似的词:')
for word, score in similar_words:
    print(f'{word}: {score}')

# 6. 词向量的简单运算
result = model.wv.most_similar(positive=['王后', '男人'], negative=['女人'], topn=1)
print('王后 + 男人 - 女人 = ')
print(result)



5.总结

优势和局限性

优势:

  • 高效性: 相比传统的共现矩阵和 SVD 分解,Word2Vec 在大规模语料上训练速度更快。
  • 语义捕捉: 能够有效捕捉词语的语义和语法关系。

局限性:

  • 上下文独立: Word2Vec 为每个词生成固定的向量,无法处理词语的多义性和上下文依赖性
  • 缺乏句子级别表示: 仅对词语进行嵌入,无法直接用于句子或段落的表示。
  • 对未登录词的处理: 无法生成未在词汇表中出现的词语的向量。

应用场景

  1. 词语相似度计算: 通过计算词向量之间的相似度,获取与给定词语语义相近的词。
  2. 文本分类和聚类: 将文本表示为词向量的组合,用于分类或聚类任务。
  3. 机器翻译: 通过训练词向量实现词语间的语义映射,辅助翻译。
  4. 信息检索: 改进搜索引擎的关键词匹配,提升用户查询的匹配质量。
  5. 情感分析: 捕捉文本中情感信息,应用于情绪监控等领域。

改进和扩展

  1. FastText: 将词语分解为字符 n-gram,能够处理未登录词和词语的内部结构。

  2. GloVe (Global Vectors for Word Representation): 结合全局语料词共现信息,利用矩阵分解的方法生成词向量。

  3. ELMo (Embeddings from Language Models): 基于词向量的语言模型,生成上下文敏感的词向量,解决词语的多义性问题。

  4. BERT (Bidirectional Encoder Representations from Transformers): 利用 Transformer 架构,生成深度的上下文表示,可用于句子和段落级别的嵌入。

Word2Vec 是自然语言处理领域的重要里程碑,通过将词语映射到连续向量空间,开创了基于分布式表示的词语语义建模方法。虽然存在一些局限,但模型的后续发展(如 FastText、BERT 等)的发展竞相出现。对于从事 NLP 研究和应用的人员,深入理解 Word2Vec 的原理和实现,有助于更好地应用和改进词向量的建模技术。

二、GloVe

GloVe(Global Vectors for Word Representation)是由斯坦福大学的 Jeffrey Pennington、Richard Socher 和 Christopher D. Manning 于 2014 年提出的一种词向量表示模型。GloVe 的主要思想是结合全局的词共现统计信息与局部的上下文窗口信息,通过矩阵分解的方式,生成能够捕捉词语语义和语法特征的高质量词向量。与基于预测的模型(如 Word2Vec)不同,GloVe 直接利用词语的共现概率,旨在更好地捕捉全局语义关系。

1.基本原理

GloVe 模型的核心思想是:词语的语义关系可以通过词共现概率的比值来捕捉。在大规模语料库中,统计词语之间的共现次数,可以得到一个词共现矩阵。GloVe 利用这个矩阵,通过最小化词向量与共现概率对数之间的差异,学习出词向量表示

词共现矩阵

  • 定义: 在给定语料库中,统计每个词对 ( ( i , j ) ) ((i,j)) ((i,j)) 共同出现的次数 X i j X_{ij} Xij,形成词共现矩阵 X X X
  • 共现概率: 词 j j j 在给定词 i i i 的条件下出现的概率为:

P i j = X i j X i P_{ij} = \frac{X_{ij}}{X_i} Pij=XiXij

其中, X i = ∑ k X i k X_i = \sum_k X_{ik} Xi=kXik 是词 i i i 出现时所有共现词的总次数。

损失函数的构建

GloVe 的目标是找到一个映射,使得词向量之间的关系能够反映词语的共现概率。具体来说,模型希望满足以下关系:

w i T w j + b i + b j = log ⁡ ( X i j ) w_i^T w_j + b_i + b_j = \log(X_{ij}) wiTwj+bi+bj=log(Xij)

其中:

  • w i w_i wi w j w_j wj 分别是词 i i i 和词 j j j 的词向量。
  • b i b_i bi b j b_j bj 是对应的偏置项。

为了实现这一目标,GloVe 定义了以下损失函数:

J = ∑ i , j = 1 V f ( X i j ) ( w i T w j + b i + b j − log ⁡ X i j ) 2 J = \sum_{i,j=1}^{V} f(X_{ij}) \left( w_i^T w_j + b_i + b_j - \log X_{ij} \right)^2 J=i,j=1Vf(Xij)(wiTwj+bi+bjlogXij)2

其中:

  • V V V 是词汇表的大小。
  • f ( X i j ) f(X_{ij}) f(Xij) 是权重函数,控制不同频次的词对对损失的贡献。

权重函数

为了避免高频词对损失函数的主导,同时又不忽略低频词,GloVe 采用如下的权重函数:

f ( x ) = { ( x x max ) α if  x < x max 1 if  x ≥ x max f(x) = \begin{cases} \left( \frac{x}{x_{\text{max}}} \right)^\alpha & \text{if } x < x_{\text{max}} \\ 1 & \text{if } x \geq x_{\text{max}} \end{cases} f(x)={(xmaxx)α1if x<xmaxif xxmax

常用的参数取值为 α = 0.75 \alpha = 0.75 α=0.75 x max = 100 x_{\text{max}} = 100 xmax=100


2.训练方法和实践步骤

模型训练步骤

  1. 数据预处理: 对语料库进行分词,去除停用词等预处理操作。
  2. 构建词共现矩阵: 设定窗口大小 w w w,统计词对共现次数 X i j X_{ij} Xij
  3. 初始化参数: 随机初始化词向量 w i w_i wi w j w_j wj 以及偏置项 b i b_i bi b j b_j bj
  4. 定义损失函数: 使用上述损失函数 J J J
  5. 优化损失函数: 采用 AdaGrad 等优化算法,最小化损失函数 J J J
  6. 获取最终词向量: 训练完成后,通常将 w i w_i wi w j w_j wj 相加或取平均,作为词 i i i 的最终表示。

优化算法

  • AdaGrad: 自适应学习率优化算法,适合处理稀疏数据和大规模数据集。
  • 并行化: GloVe 的训练过程中可以进行并行化,加速模型的训练。

实践指南

  1. 数据准备
  • 收集语料: 获取大规模、多样性的文本数据集,如维基百科、新闻语料等。
  • 数据预处理: 清除噪声,去除标点、统一大小写等。
  • 分词处理: 对文本进行分词,进行去除停用词操作。
  1. 构建词共现矩阵
  • 设定窗口大小: 通常选择 5 到 10。
  • 统计词共现次数: 统计词对共现次数,并构造词语之间的共现矩阵。
  1. 模型训练
  • 设置超参数: 选择词向量维度(如 50、100、300)、学习率等。
  • 选择优化算法: 选择常用的 AdaGrad 等优化算法。
  • 训练模型: 优化损失函数,最小化目标函数。
  1. 模型评估
  • 相似度测试: 测试词向量之间的余弦相似度是否能反映语义关系上的相近性。
  • 下游任务应用: 在具体任务中进行验证和测试,评估性能表现。

3.python代码实现

from glove import Corpus, Glove

# 准备语料
sentences = [
    ['我', '喜欢', '自然', '语言', '处理'],
    ['词向量', '是', 'NLP', '的重要', '组成部分'],
    ['GloVe', '模型', '利用', '词共现', '统计信息']
]

# 构建词共现矩阵
corpus = Corpus()
corpus.fit(sentences, window=5)

# 训练 GloVe 模型
glove = Glove(no_components=100, learning_rate=0.05)
glove.fit(corpus.matrix, epochs=20, no_threads=4, verbose=True)
glove.add_dictionary(corpus.dictionary)

# 获取词向量
vector = glove.word_vectors[glove.dictionary['自然']]

# 查找相似词
similar = glove.most_similar('自然', number=5)
print(similar)

4.总结

4.1. 优势和局限性

优势

  • 全局统计信息: 利用全局共现统计信息,能更精确捕捉更丰富的语义关系。
  • 高效性: 在小样本数据的高频训练下表现优秀,内存利用率较高,适用于大规模数据。
  • 稀疏性处理: 能够较好地处理稀疏性信息。

局限性

  • 内存消耗较大: 构建矩阵时内存开销较大,适合离线处理。
  • 上下文独立: 与 Word2Vec 一样,无法处理词语的多义性和上下文变化。
  • 数据依赖: GloVe 依赖于全局的词共现矩阵,无法动态更新词向量。

4.2. 与 Word2Vec 的比较

  • 信息利用方式:

    • Word2Vec: 基于局部上下文的预测,利用滑动窗口中的词语共现信息。
    • GloVe: 结合全局的词共现统计信息,更全面地捕捉词语之间的关系。
  • 模型基本原理:

    • Word2Vec: 属于预测型模型,基于神经网络。
    • GloVe: 属于基于计数的模型,进行矩阵分解。
  • 训练效率:

    • Word2Vec: 在大规模语料上训练速度较快,但需要高频迭代多个训练次数。
    • GloVe: 预先构造词共现矩阵,训练次数较少但构造成本高。
  • 性能差异:

    • 词类比任务: 两者性能相近,GloVe 有时表现更好。
    • 计算复杂性: GloVe 由于依赖共现矩阵,Word2Vec 更节省内存。

4.3. 应用场景

  • 词语相似度计算: 评估词语之间的相似性和关联性。
  • 文本分类和聚类: 将文本表示为词向量的组合,用于分类或聚类任务。
  • 机器翻译: 通过捕捉语义关系,辅助机器翻译任务。
  • 信息检索和问答系统: 改进搜索结果的相关性,提升用户体验。
  • 情感分析: 捕捉文本中的情感倾向,应用于舆情监控等领域。

GloVe 模型通过融合全局的词共现统计信息,为词向量表示提供了强有力的工具。它在捕捉词语的语义和语法关系方面表现出色,已成为自然语言处理领域的重要方法之一。尽管存在内存需求大、无法处理上下文等局限,但通过改进和扩展,GloVe 仍具有广阔的应用前景。深入理解 GloVe 的原理和实现,有助于更好地应用词向量技术,解决实际的 NLP 问题。

三、FastText

FastText 是由 Facebook 的研究团队于 2016 年提出的一种用于高效学习词向量和文本分类的模型。它在 Word2Vec 的基础上进行了改进,能够处理未登录词(out-of-vocabulary words)和捕捉词语内部的形态信息。FastText 将每个词表示为字符 n-gram 的集合,从而可以更好地捕捉词的拼写和形态学特征,特别适用于处理大量的词汇和罕见词。

1.基本原理

  1. 词表示方式

FastText 的核心思想是将每个词表示为其字符 n-gram 的集合,并将词本身也视为一个特殊的 n-gram。具体来说:

  • 字符 n-gram: 将一个词分解为所有可能的 n-gram,通常 n n n 的取值范围为 3 到 6。
  • 词的表示: 一个词的向量表示是其所有 n-gram 向量的和或平均。

示例:

对于词 “apple”,取 n = 3 n=3 n=3,则其字符 3-gram 有:

  • <ap, app, ppl, ple, le>

这里,<> 分别表示词的开始和结束。

2.模型结构

FastText 的模型架构与 Word2Vec 的 Skip-Gram 模型类似,但在输入层处理上有所不同:

  • 输入层: 词由字符 n-gram 的集合表示。
  • 隐藏层: 将 n-gram 向量投影到隐藏层。
  • 输出层: 通过 softmax 或近似方法,预测上下文词

FastText 旨在最大化输入词与上下文词之间的共现概率。其损失函数与 Skip-Gram 模型类似,但在词向量表示上使用了 n-gram 的集合。

3.训练方法和实践步骤

3.1. 模型训练

  1. 数据预处理
  • 分词: 将语料库切分为词词序列。
  • 生成 n-gram: 对于每个词,生成对应的字符 n-gram 集合。
  1. 训练过程
  • 输入表示: 对于中心词,获取其所有的字符 n-gram,并查找对应的 n-gram 向量。
  • 上下文预测: 利用中心词的 n-gram 向量,预测上下文词的概率分布。
  • 优化目标: 最小化负对数似然损失,或使用负采样进行高效训练。
  1. 采用优化技术
  • 负采样 (Negative Sampling): 减少计算复杂度,提高清训练速度。
  • 分层 softmax (Hierarchical Softmax): 对大型词汇表进行高效的概率计算。

4.python代码实现

使用 Python 接口

import fasttext

# 训练词向量模型
model = fasttext.train_unsupervised('corpus.txt', model='skipgram', dim=100, minn=3, maxn=6)

# 获取词向量
vector = model.get_word_vector('自然语言处理')

# 查找相似词
similar_words = model.get_nearest_neighbors('自然语言处理', k=5)
print(similar_words)

文本分类示例

import fasttext

# 训练文本分类模型
model = fasttext.train_supervised('train.txt', label_prefix='__label__', epoch=5, lr=0.1)

# 模型评估
result = model.test('test.txt')
print('Precision:', result.precision)
print('Recall:', result.recall)

# 预测新样本
labels, probabilities = model.predict('这是一个新的评论', k=2)
print(labels, probabilities)

5.总结

优势

  1. 处理未登录词

由于 FastText 使用了字符 n-gram,当遇到未出现在训练集中出现的词时,仍然可以通过其字符 n-gram 获取词向量。这使得模型在处理罕见词或新词时表现更佳。

  1. 捕捉词形信息

字符 n-gram 能够捕捉到前缀、后缀和词根等信息,处理形态丰富的语言(如法语、德语等)尤为有利。

  1. 高效性

FastText 在保持高性能的同时,具有较快的训练速度和较低的内存占用,适合大规模数据训练。

应用场景

  1. 词向量表示
  • 语义相似度计算:获取词语的向量表示,计算词语之间的相似度。
  • 文本表示:将句子或文档表示为词向量的组合,用于各种 NLP 任务。
  1. 文本分类
  • 监督学习:FastText 提供了高效的文本分类算法,适用于情感分析、主题分类等任务。
  • 多语言支持:在多语言环境下,FastText 能够高效处理多种语言的文本分类。
  1. 命名实体识别和词性标注
  • 利用词的形态特征:通过字符 n-gram,模型能够更好地识别词的类型和特征。

FastText 通过引入字符 n-gram,将词的内部结构纳入模型,有效地解决了未登录词和低频词的表示问题。其高效性和易用性使其在自然语言处理的多个领域得到了广泛应用。对于需要处理大量文本数据的任务,FastText 是一个强大的工具。通过深入理解其原理和实践方法,能够更好地应用 FastText,提高 NLP 模型的性能。

四、对比总结

特性Word2VecGloVeFastText
训练原理基于局部上下文窗口基于全局词共现矩阵基于局部上下文窗口 + 子词信息
处理多义词无法处理无法处理有一定能力处理(基于子词)
未见词处理无法处理无法处理可以通过子词 n-grams 处理
计算效率高效(负采样)计算复杂度较高训练相对慢,但推理时效率高
语义捕捉能力强(依赖上下文)强(依赖全局信息)较弱,特别适合低资源语言
适用场景适合大规模语料,常见语言适合大规模语料,需要全局语义的场景适合多语言任务,低资源语言或未见词场景
  • Word2Vec 适合在大规模语料上快速训练词向量,能够很好地捕捉词的局部语义关系,但对多义词和未见词无能为力。
  • GloVe 则侧重于全局的语料统计信息,适合需要全局语义关系的任务,然而其计算代价较高且在未见词处理方面存在局限。
  • FastText 通过子词的 n-grams 技术,能很好地处理形态丰富语言和未见词问题,是一个兼顾效率和表现的改进模型。

结~~~


http://www.kler.cn/news/334953.html

相关文章:

  • Hive数仓操作(十七)
  • 趣味SQL | 从围棋收官到秦楚大战的数据库SQL实现(下)
  • Linux高级编程_29_信号
  • 【NIO基础】NIO(非阻塞 I/O)和 IO(传统 I/O)的区别,以及 NIO 的三大组件详解
  • EXCEL_光标百分比
  • 计算机网络:物理层 —— 物理层下的传输媒体
  • 深入理解闭包【JavaScript】
  • 【百度文心智能体】想开发爆款智能体?来看看 万圣节之夜探秘者 智能体开发流程大揭秘
  • 东方仙盟——软件终端架构思维———未来之窗行业应用跨平台架构
  • IDEA使用技巧
  • 信息学奥赛复赛复习13-CSP-J2021-02插入排序-排序稳定性、插入排序、sort排序、结构体、计数排序
  • 大数据复习知识点6
  • Vueron引领未来出行:2026年ADAS激光雷达解决方案上市路线图深度剖析
  • windows下DockerDesktop命令行方式指定目录安装
  • OJ题目!!!(https://oj.aicoders.cn/group/3481/training/33087/problem/1138)
  • Ubuntu如何如何安装tcpdump
  • 两个wordpress网站共用一个数据库的数据表
  • Python编写的贪吃蛇小游戏
  • 基于ssm 框架的java 开发语言的 在线教育学习平台系统设计与实现 源码 论文
  • Golang 进阶5—— 反射