Loading...
墨滴

张春成

2021/07/03  阅读:28  主题:默认主题

图解词向量与图论的代码

图解词向量与图论的代码

本文是列出以上两篇文章《图解词向量》与《图解图论分析》的相关代码。


程序流程图

从工程的角度,我们建立不同模块的工作流程图。 分析及可视化流程如下图所示

Graph-WordVec-GraphAnalysis.svg
Graph-WordVec-GraphAnalysis.svg

分析代码如下

词向量分析及可视化代码

  • 引用的包
import pandas as pd
import jieba
from tqdm.auto import tqdm

import numpy as np
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from sklearn.cluster import SpectralClustering
from sklearn.cluster import KMeans

import plotly.express as px
  • 分词的工具类
class VeryImportantTalk(object):
    ''' The Analysis of the VeryImportantTalk '''
    def __init__(self, path='VeryImportantTalk.txt', encoding='utf-8'):
        ''' Initialization '''
        content = open(path, 'r', encoding=encoding).read()
        df = pd.DataFrame(columns=['Sentence''Cuts'])
        self.content = content
        self.df = df

        self.get_sentences()
        self.cut_sentences()

    def get_sentences(self, raw=None):
        ''' Get Sentences from Raw Content [raw]'''
        if raw is None:
            raw = self.content

        for e in ['。''!''a,']:
            raw = raw.replace(e, '\n')
        sentences = raw.split()

        self.df['Sentence'] = sentences

        return sentences

    def cut_sentences(self, sentences=None):
        ''' Cut every Sentence in the List of Sentences [sentences] '''
        if sentences is None:
            sentences = self.df['Sentence'].values

        cuts = []
        for s in tqdm(sentences):
            # Cut the Sentence,
            # and Discard the one-char Words
            tmp = [e for e in jieba.lcut(s) if len(e) > 1]

            # Append the Words,
            # and Discard the one-word Sentence
            if len(tmp) > 1:
                cuts.append(tmp)
            else:
                cuts.append([])

        self.df['Cuts'] = cuts

        return cuts
  • 统计词频
vit = VeryImportantTalk()
vit.df

df = vit.df.copy()
df

details = dict()

for idx in tqdm(df.index):
    for word in df.loc[idx, 'Cuts']:
        if word not in details:
            details[word] = [idx]
        else:
            details[word].append(idx)

details = pd.DataFrame(dict(Belong=details))
details['Count'] = details['Belong'].map(len)
details.sort_values(by='Count', ascending=False, inplace=True)

details[details.index] = 0

details
  • 计算词向量
for w in tqdm(details.index):
    for j in details.loc[w, 'Belong']:
        details.loc[w, df.loc[j, 'Cuts']] += 1

details
  • 流形映射
X = details[details.index].to_numpy()
a = 1
X = (X - np.mean(X, axis=a, keepdims=True)) / np.std(X, axis=a, keepdims=True)
X = X / np.max(X, axis=a, keepdims=True)
# for j in range(len(details)):
#     X[j] = X[j] / details.iloc[j]['Count']
X = X.transpose()

X_embedded = TSNE(n_components=2).fit_transform(X)
print(X_embedded.shape)

fig = px.scatter(x=X_embedded[:, 0], y=X_embedded[:, 1], title='Manifolder of Words')
fig.show()
  • 聚类分析
kmeans = KMeans(n_clusters=7, random_state=0)
labels = kmeans.fit_predict(X_embedded)

colors = []
for e in labels:
    words = details.index[labels == e]
    colors.append(words[:10])

fig = px.scatter(x=X_embedded[:, 0], y=X_embedded[:, 1], color=labels, hover_name=colors, title='Cluster of Words')
fig.show()
  • 绘制分布图或甘特图
gantt = [] # = pd.DataFrame()

for word, label in tqdm(zip(details.index, labels)):
    idxs = details.loc[word, 'Belong']
    for i in idxs:
        gantt.append({'Sentence': i, 'Label': label, 'Word': word})

gantt = pd.DataFrame(gantt)
gantt

px.scatter(gantt, x='Sentence', y='Word', color='Label', title='Word Distribution')

px.scatter(gantt, x='Sentence', y='Label', color='Label', title='Word Gantt')

for l in np.unique(labels):
    _df = gantt.query(f"Label=={l}")
    title = f'{l}: ' + ','.join(_df['Word'].unique())
    print(title)
    fig = px.scatter(_df, x='Sentence', y='Word', hover_name='Word', hover_data=['Word''Label'], title=title)
    fig.show()

图论分析及可视化代码

  • 构建最小总长度图
a = 0
b = np.argmin(dist_matrix[a])
route = [(a, b)]
inside = [a, b]
remain = [e for e in range(n) if e not in inside]
for _ in tqdm(range(n-2)):
    mat = dist_matrix[inside][:, remain]
    pos = np.unravel_index(np.argmin(mat), mat.shape)
    a = inside[pos[0]]
    b = remain[pos[1]]
    inside.append(b)
    remain.remove(b)
    route.append((a, b))

route

route_df = []
for j, r in tqdm(enumerate(route)):
    for i in [01]:
        route_df.append(dict(
            x=X_embedded[r[i]][0],
            y=X_embedded[r[i]][1],
            group=j
        ))

route_df = pd.DataFrame(route_df)
route_df
  • 计算连接度的方法
count = np.zeros(n)
for r in tqdm(route):
    count[r[0]] += 1
    count[r[1]] += 1
count
  • 绘制连接度图
fig = go.Figure()
fig.add_trace(fig1.data[0])
for d in fig2.data:
    d['line']['color'] = 'gray'
    d['showlegend'] = False
    fig.add_trace(d)
fig.update_layout({'title''Connection Graph'})
fig.show()

px.bar(sorted(count), title='Connection Degree')

张春成

2021/07/03  阅读:28  主题:默认主题

作者介绍

张春成