sklearn-LDA做主题分析

Published on Aug. 22, 2023, 12:10 p.m.

sklearn-LDA主题分析

LDA主题分析主要应用于文本分类和预测中,并可以做推荐依据进行针对推荐。

https://scikit-learn.org/stable/modules/generated/sklearn.discriminant_analysis.LinearDiscriminantAnalysis.html

import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
y = np.array([1, 1, 1, 2, 2, 2])
clf = LinearDiscriminantAnalysis()
clf.fit(X, y)

print(clf.predict([[-0.8, -1]]))
[1]
# -*- coding: utf-8 -*-

import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import LatentDirichletAllocation
# corpus = [res1,res2,res3]
res1="""

n_components: 即我们的隐含主题数,需要调参。的大小取决于我们对主题划分的需求,比如我们只需要类似区分是动物,植物,还是非生物这样的粗粒度需求,那么值可以取的很小,个位数即可。如果我们的目标是类似区分不同的动物以及不同的植物,不同的非生物这样的细粒度需求,则值需要取的很大,比如上千上万。此时要求我们的训练文档数量要非常的多。

"""
res2="""

doc_topic_prior:即我们的文档主题先验Dirichlet分布的参数。一般如果我们没有主题分布的先验知识,可以使用默认值1/。
topic_word_prior:即我们的主题词先验Dirichlet分布的参数。一般如果我们没有主题分布的先验知识,可以使用默认值 1/.

"""

res3="""

learning_method: 即LDA的求解算法。有 ‘batch’ 和 ‘online’两种选择。 ‘batch’即我们在原理篇讲的变分推断EM算法,而"online"即在线变分推断EM算法,在"batch"的基础上引入了分步训练,将训练样本分批,逐步一批批的用样本更新主题词分布的算法。默认是"online"。选择了‘online’则我们可以在训练时使用partial_fit函数分布训练。不过在scikit-learn 0.20版本中默认算法会改回到"batch"。建议样本量不大只是用来学习的话用"batch"比较好,这样可以少很多参数要调。而样本太多太大的话,"online"则是首选了。

"""

res1=' '.join(res1)
res2=' '.join(res2)
res3=' '.join(res3)
res1

'\n \n n _ c o m p o n e n t s :   即 我 们 的 隐 含 主 题 数  , 需 要 调 参 。  的 大 小 取 决 于 我 们 对 主 题 划 分 的 需 求 , 比 如 我 们 只 需 要 类 似 区 分 是 动 物 , 植 物 , 还 是 非 生 物 这 样 的 粗 粒 度 需 求 , 那 么  值 可 以 取 的 很 小 , 个 位 数 即 可 。 如 果 我 们 的 目 标 是 类 似 区 分 不 同 的 动 物 以 及 不 同 的 植 物 , 不 同 的 非 生 物 这 样 的 细 粒 度 需 求 , 则  值 需 要 取 的 很 大 , 比 如 上 千 上 万 。 此 时 要 求 我 们 的 训 练 文 档 数 量 要 非 常 的 多 。 \n \n'

下面开始

特征选择 可以tfidfvectorizer,CountVectorizer,或者word2vec等。
当然也可以选择bert,不过,中文预训练多数都存在分词问题。

corpus = [res1,res2,res3]
cntVector = CountVectorizer()
cntTf = cntVector.fit_transform(corpus)
# print(type(cntTf))

lda = LatentDirichletAllocation(n_components=2,learning_offset=50.)
docres = lda.fit_transform(cntTf)

# print(docres)
print(lda.components_)
[[1.49848591 5.49843166 0.50126498 1.49848591 1.49848591 5.49843166
  0.50126498 0.50129923 1.49848591 1.49848591 1.49848591 1.49848591
  1.49848591 1.49848591 1.49848591 0.50126498 0.50126498 0.50126498
  0.50126498 1.49848591 1.49848591 1.49848591 1.49848591 1.49848591
  1.49848591 1.49848591 1.49848591 1.49848591]
 [0.50151409 0.50156834 1.49873502 0.50151409 0.50151409 0.50156834
  1.49873502 2.49870077 0.50151409 0.50151409 0.50151409 0.50151409
  0.50151409 0.50151409 0.50151409 1.49873502 1.49873502 1.49873502
  1.49873502 0.50151409 0.50151409 0.50151409 0.50151409 0.50151409
  0.50151409 0.50151409 0.50151409 0.50151409]]

def print_top_words(model, feature_names, n_top_words):
    #打印每个主题下权重较高的term
    for topic_idx, topic in enumerate(model.components_):
        print("Topic #%d:" % topic_idx)
        print(" ".join([feature_names[i]
                        for i in topic.argsort()[:-n_top_words - 1:-1]]))
    print
    #打印主题-词语分布矩阵
    print (model.components_)

n_top_words=20
tf_feature_names = cntVector.get_feature_names()
print_top_words(lda, tf_feature_names, n_top_words)
Topic #0:
batch online 默认是 即我们在原理篇讲的变分推断em算法 learn learning_method 不过在scikit 两种选择 则我们可以在训练时使用partial_fit函数分布训练 则是首选了 即lda的求解算法 逐步一批批的用样本更新主题词分布的算法 即在线变分推断em算法 将训练样本分批 建议样本量不大只是用来学习的话用 比较好 的基础上引入了分步训练 而样本太多太大的话 这样可以少很多参数要调 选择了
Topic #1:
一般如果我们没有主题分布的先验知识 doc_topic_prior topic_word_prior 可以使用默认值1 可以使用默认值 即我们的文档主题先验dirichlet分布的参数 即我们的主题词先验dirichlet分布的参数 batch online 默认是 则是首选了 learn learning_method 不过在scikit 两种选择 则我们可以在训练时使用partial_fit函数分布训练 即在线变分推断em算法 即lda的求解算法 逐步一批批的用样本更新主题词分布的算法 即我们在原理篇讲的变分推断em算法
[[1.49848591 5.49843166 0.50126498 1.49848591 1.49848591 5.49843166
  0.50126498 0.50129923 1.49848591 1.49848591 1.49848591 1.49848591
  1.49848591 1.49848591 1.49848591 0.50126498 0.50126498 0.50126498
  0.50126498 1.49848591 1.49848591 1.49848591 1.49848591 1.49848591
  1.49848591 1.49848591 1.49848591 1.49848591]
 [0.50151409 0.50156834 1.49873502 0.50151409 0.50151409 0.50156834
  1.49873502 2.49870077 0.50151409 0.50151409 0.50151409 0.50151409
  0.50151409 0.50151409 0.50151409 1.49873502 1.49873502 1.49873502
  1.49873502 0.50151409 0.50151409 0.50151409 0.50151409 0.50151409
  0.50151409 0.50151409 0.50151409 0.50151409]]

/usr/local/lib/python3.7/dist-packages/sklearn/utils/deprecation.py:87: FutureWarning: Function get_feature_names is deprecated; get_feature_names is deprecated in 1.0 and will be removed in 1.2. Please use get_feature_names_out instead.
  warnings.warn(msg, category=FutureWarning)

TF-IDF 构造词频矩阵

from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
# 多个文档构成的列表
documnets = ['今天 天气 很好 啊','今天 天气 确实 很好']
tf_idf_vectorizer = TfidfVectorizer()
# 构造词频矩阵
tf_idf = tf_idf_vectorizer.fit_transform(documnets)
# 获取特征词
feature_names = tf_idf_vectorizer.get_feature_names()
# 词频矩阵
matrix = tf_idf.toarray()
df = pd.DataFrame(matrix,columns=feature_names)
df
/usr/local/lib/python3.7/dist-packages/sklearn/utils/deprecation.py:87: FutureWarning: Function get_feature_names is deprecated; get_feature_names is deprecated in 1.0 and will be removed in 1.2. Please use get_feature_names_out instead.
  warnings.warn(msg, category=FutureWarning)

.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}

今天 天气 很好 确实
0 0.577350 0.577350 0.577350 0.000000
1 0.448321 0.448321 0.448321 0.630099

.colab-df-container {
display:flex;
flex-wrap:wrap;
gap: 12px;
}

.colab-df-convert {
background-color: #E8F0FE;
border: none;
border-radius: 50%;
cursor: pointer;
display: none;
fill: #1967D2;
height: 32px;
padding: 0 0 0 0;
width: 32px;
}

.colab-df-convert:hover {
background-color: #E2EBFA;
box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
fill: #174EA6;
}

[theme=dark] .colab-df-convert {
background-color: #3B4455;
fill: #D2E3FC;
}

[theme=dark] .colab-df-convert:hover {
background-color: #434B5C;
box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
fill: #FFFFFF;
}

const buttonEl =
document.querySelector(‘#df-06838677-5dfa-48e9-a490-fc3b735f7e79 button.colab-df-convert’);
buttonEl.style.display =
google.colab.kernel.accessAllowed ? ‘block’ : ‘none’;

async function convertToInteractive(key) {
const element = document.querySelector(‘#df-06838677-5dfa-48e9-a490-fc3b735f7e79’);
const dataTable =
await google.colab.kernel.invokeFunction(‘convertToInteractive’,
[key], {});
if (!dataTable) return;

const docLinkHtml = ‘Like what you see? Visit the ‘ +
‘<a target=”_blank” href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook’
+ ‘ to learn more about interactive tables.’;
element.innerHTML = ‘’;
dataTable[‘output_type’] = ‘display_data’;
await google.colab.output.renderOutput(dataTable, element);
const docLink = document.createElement(‘div’);
docLink.innerHTML = docLinkHtml;
element.appendChild(docLink);
}

代码地址:

https://colab.research.google.com/drive/1hgp-XSzDKYdVUIpy31f_G6K42VzaZJKO#scrollTo=QC4gw1WojGY_