【NLP】Word Embeddingを利用して中国語の自動要約を実現


この記事では、Word Embedding を使用して中国語の自動要約を実現し、 Gensim word2vec モデルを使用して Word Embedding を生成する方法を例を使用して紹介します。

主な手順

1) 中国語コーパスをインポートする
2) この中国語コーパスに基づいて word2vec モデルを構築し、各単語の単語ベクトルを取得するようにトレーニングする;
3) 各トピックとその概要説明情報を含む文書をインポートし、文書を前処理するそれを単語ベクトルに変換します ;
4) クラスタリングの方法を使用して、各トピックのいくつかのキーワードを生成します。

中国語コーパス

この記事では総合ラボの総合ニュースコーパスを使用しており、https://github.com/garfieldkai/word2vec/blob/master/data/corpus.txt
データリンクからダウンロードしたファイル名は次のとおりです。news_sohusite_xml.smarty.tar.gz

データの前処理

1) 元のデータ CD を元のファイル ディレクトリに解凍して表示し
、解凍コマンドを実行します。

tar -zvxf news_sohusite_xml.smarty.tar.gz

ファイルを取得しnews_sohusite_xml.datvim次のコマンドでファイルを開きます。

vim news_sohusite_xml.smarty.dat

以下の結果が得られます。
データ内容
2) コンテンツの取り出し作成中のコンテンツ
を取り出すには、以下のコマンドを実行します。<content> </content>

cat news_sohusite_xml.smarty.dat | iconv -f gbk -t utf-8 -c | grep "<content>"  > corpus.txt 

窓の下でも使用可能

type news_sohusite_xml.smarty.dat | iconv -f gbk -t utf-8 -c | findstr "<content>"  > corpus.txt 

vim で開くことができる corpus.txt という名前のファイルを取得します。

vim corpus.txt

以下の効果が得られます。
コーパス
3) 単語分割
jieba 単語分割を使用してストップワードなどをフィルタリングします。コードは次のとおりです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/7/8 11:39
# @Author  : Alvaro Pang
# @File    : cutWord.py
# @Software: PyCharm

import jieba
import numpy as np

filePath = 'corpus.txt'
fileSeqWordDonePath = 'corpusSeqDone_1.txt'


# 打印中文列表
def PrintListChinese(list):
    for i in range(len(list)):
        print(list[i])


# 打印文件内容到列表
fileTrainRead = []
with open(filePath, 'r', encoding='utf-8') as fileTrainRaw:
    for line in fileTrainRaw:  # 按行读取文件
        fileTrainRead.append(line)

# jieba分词后保存在列表中
fileTrainSeq = []
for i in range(len(fileTrainRead)):
    fileTrainSeq.append([' '.join(list(jieba.cut(fileTrainRead[i][9:-11], cut_all=False)))])
    if i % 10000 == 0:
        print(i)

# 保存分词结果到文件中
with open(fileSeqWordDonePath, 'w', encoding='utf-8') as fW:
    for i in range(len(fileTrainSeq)):
        fW.write(fileTrainSeq[i][0])
        fW.write('\n')

corpusSegDone_1.txt という名前のファイルを取得できます。ファイルに読み取られた各行について、吃音単語分割を使用する場合、0 から末尾までのすべての単語分割が実行されるわけではなく、[9:-11] 単語分割が実行されることに注意してください。 (行 22 のように: fileTrainRead[i][9:-11] )、各行の先頭と末尾が削除されます (プレス リリース)。次の図に示す結果が得られます。
単語分割結果

単語ベクトルを生成する

Gensim word2vec ライブラリを使用して単語ベクトルを生成します。コードは次のとおりです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/7/10 1:07
# @Author  : Alvaro Pang
# @File    : wordvectors.py
# @Software: PyCharm

import warnings
import logging
import os.path
import sys
import multiprocessing

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

# 忽略警告
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')

if __name__ == '__main__':
    program = os.path.basename(sys.argv[0])  # 读取当前文件的文件名
    logger = logging.getLogger(program)
    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s', level=logging.INFO)
    logger.info("running %s" % ' '.join(sys.argv))

    # inp为输入语料,outp1为输出模型,outp2为vector格式的模型
    inp = './corpusSeqDone_1.txt'
    out_model = './corpusSeqDone_1.model'
    out_vector = './corpusSeqDone_1.vector'

    # 训练skip-gram模型
    model = Word2Vec(LineSentence(inp), vector_size=50, window=5, min_count=5, workers=multiprocessing.cpu_count())

    # 保存模型
    model.save(out_model)
    # 保存词向量
    model.wv.save_word2vec_format(out_vector, binary=False)

ドキュメントの単語を単語ベクトルに変換します。

データを前処理し、スキップグラム モデルを使用してワード ベクトルに変換します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/7/13 21:10
# @Author  : Alvaro Pang
# @File    : textvectors.py
# @Software: PyCharm
# 采用word2vec词聚类方法抽取关键词1——获取文本词向量表示
import sys, codecs
import pandas as pd
import numpy as np
import jieba
import jieba.posseg
import gensim
import warnings

warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')  # 忽略警告


# 返回特征词向量
def getWordVec(wordList, model):
    name, vecs = [], []
    for word in wordList:
        word = word.replace('\n', '')
        try:
            if word in model:  # 模型中存在该词的向量表示
                name.append(word)
                vecs.append(model[word])
        except KeyError:
            continue
    a = pd.DataFrame(name, columns=['word'])
    b = pd.DataFrame(np.array(vecs, dtype='float'))
    return pd.concat([a, b], axis=1)


# 数据预处理操作:分词、去停用词、词性筛选
def dataPrepos(text, stopkey):
    l = []
    pos = ['n', 'nz', 'v', 'vd', 'vn', 'l', 'a', 'd']  # 定义选取的词性
    seq = jieba.posseg.cut(text)  # 分词
    for i in seq:
        if i.word not in l and i.word not in stopkey and i.flag in pos:  # 去重+去停用词+词性筛选
            l.append(i.word)
    return l


# 根据数据获取候选关键词词向量
def buildAllWordsVecs(data, stopkey, model):
    idList, titleList, abstractList = data['id'], data['title'], data['abstract']
    for index in range(len(idList)):
        id = idList[index]
        title = titleList[index]
        abstract = abstractList[index]
        l_ti = dataPrepos(title, stopkey)  # 处理标题
        l_ab = dataPrepos(abstract, stopkey)  # 处理摘要
        # 获取候选关键词的词向量
        words = np.append(l_ti, l_ab)  # 拼接数组元素
        words = list(set(words))  # 数组元素去重,得到候选关键词列表
        wordvecs = getWordVec(words, model)  # 获取候选关键词的词向量表示
        # 词向量写入csv文件,每个词400维
        data_vecs = pd.DataFrame(wordvecs)
        data_vecs.to_csv('./vecs/wordvecs_' + str(id) + '.csv', index=False)
        print("document ", id, " well done.")


def main():
    # 读取数据
    dataFile = './sample_data.csv'
    data = pd.read_csv(dataFile)
    # 停用词表
    stopkey = [w.strip() for w in codecs.open('stopWord.txt', 'r', encoding='utf-8').readlines()]
    # 词向量模型
    inp = 'corpusSeqDone_1.vector'
    model = gensim.models.KeyedVectors.load_word2vec_format(inp, binary=False)
    buildAllWordsVecs(data, stopkey, model)


if __name__ == '__main__':
    main()

トピックごとにキーワードを生成する

クラスタリング手法は、候補キーワードの単語ベクトルをクラスタリングして分析するために使用されます。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/7/14 23:08
# @Author  : Alvaro Pang
# @File    : clustertopics.py
# @Software: PyCharm
# 采用word2vec词聚类方法抽取关键词2——根据候选关键词的词向量进行聚类分析
import sys, os
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math

# 对词向量采用K-mean聚类抽取topK关键词
topK = 6
os.environ["OMP_NUM_THREADS"] = '1'


def getkeywords_kmeans(data, topK):
    words = data['word']  # 词汇
    vecs = data.iloc[:, 1:]  # 向量表示
    kmeans = KMeans(n_clusters=1, random_state=10).fit(vecs)
    labels = kmeans.labels_  # 类别结果标签
    labels = pd.DataFrame(labels, columns=['label'])
    new_df = pd.concat([labels, vecs], axis=1)
    df_count_type = new_df.groupby('label').size()  # 各类别统计个数
    print(df_count_type)
    vec_center = kmeans.cluster_centers_  # 聚类中心

    # 计算距离(相似性)采用欧式距离
    distances = []
    vec_words = np.array(vecs)  # 候选关键词向量,dataFrame转array
    vec_center = vec_center[0]  # 第一个类别聚类中心,本例只有一个类别
    length = len(vec_center)  # 向量维度
    for index in range(len(vec_words)):  # 候选关键词个数
        cur_wordvec = vec_words[index]  # 当前词语的词向量
        dis = 0  # 向量距离
        for index2 in range(length):
            dis += (vec_center[index2] - cur_wordvec[index2]) * (vec_center[index2] - cur_wordvec[index2])
        dis = math.sqrt(dis)
        distances.append(dis)
    distances = pd.DataFrame(distances, columns=['dis'])

    result = pd.concat([words, labels, distances], axis=1)  # 拼接词语与其对应中心的距离
    result = result.sort_values(by="dis", ascending=True)  # 按照距离大小进行升序排列

    # 将用于聚类的数据的特征维度将到2维
    pca = PCA(n_components=2)
    new_pca = pd.DataFrame(pca.fit_transform(new_df))

    # 可视化
    d = new_pca[new_df['label'] == 0]
    plt.plot(d[0], d[1], 'r.')
    d = new_pca[new_df['label'] == 1]
    plt.plot(d[0], d[1], 'go')
    d = new_pca[new_df['label'] == 2]
    plt.plot(d[0], d[1], 'b*')
    plt.gcf().savefig('kmeans.png')
    plt.show()

    # 抽取排名前topk个词语作为文本关键词
    wordlist = np.array(result['word'])  # 选择词汇列并转换成数组格式
    word_split = [wordlist[x] for x in range(0, topK)]  # 抽取前topK个词汇
    word_split = " ".join(word_split)
    return word_split


def main():
    # 读取数据集
    dataFile = 'sample_data.csv'
    articleData = pd.read_csv(dataFile)
    ids, titles, keys = [], [], []

    rootdir = "vecs"  # 词向量文件根目录
    fileList = os.listdir(rootdir)  # 列出文件夹下所有的目录与文件
    # 遍历文件
    for i in range(len(fileList)):
        filename = fileList[i]
        path = os.path.join(rootdir, filename)
        if os.path.isfile(path):
            data = pd.read_csv(path)  # 读取词向量文件数据
            article_keys = getkeywords_kmeans(data, topK)  # 聚类算法得到当前文件的关键词
            print(article_keys)
            article_keys = article_keys
            # 根据文件名获得文章id以及标题
            (shortname, extension) = os.path.splitext(filename)  # 得到文件名和文件扩展名
            t = shortname.split('_')
            article_id = int(t[len(t) - 1])  # 获得文章id
            article_tit = articleData[articleData.id == article_id]['title']  # 获得文章标题
            article_tit = list(article_tit)[0]  # series转成字符串
            ids.append(article_id)
            titles.append(article_tit)
            keys.append(article_keys)
    # 将所有结果写入文件
    result = pd.DataFrame({
    
    "id": ids, "title": titles, "key": keys}, columns=["id", "title", "key"])
    result = result.sort_values(by='id', ascending=True)
    result.to_csv('keys_word2vec.csv', index=False)


if __name__ == '__main__':
    main()

実行結果を確認する

次のように、トピックごとに生成されたキーワードを確認します。
キーワード

参考文献

  1. 「シンプルな組み込み - 原理分析と応用実践」Wu Maogui および Wang Honxing 著
  2. 総合コーパス word2vec で単語ベクトルを取得
  3. Word2Vec を使用した中国語単語ベクトルのトレーニング (1)

おすすめ

転載: blog.csdn.net/ARPOSPF/article/details/131616305