You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python执行K-means文本聚类?业务ID分类聚类方案咨询

嘿,我来帮你捋清楚这个商家聚类的问题~

一、你的思路可行性分析

首先得说,你的思路有一定合理性,但存在几个容易踩的坑:

  • 手动构建类别字典分组太主观了:比如像"Wine & Pizza"和"Gastropubs & Wine"这种有重叠标签的,手动分组很容易忽略它们的关联,而且标签数量一多,手动分组效率极低还容易出错。
  • 更顺的路径应该是:先把每个商家的标签集合转成机器能理解的数值向量,再直接用K-means聚类,让模型自动捕捉标签之间的关联,得到更客观的簇结构,不用提前手动给标签分组。
二、针对你的数据的Python最优实现

你的数据是每个商家对应多个标签,属于多标签短文本聚类场景,直接按下面的步骤来就行:

1. 先把数据整理成顺手的格式

把你的列表转成字典,后续处理更方便:

business_data = {
    "business_id_a": ["Food", "Restaurant", "Wine & Pizza"],
    "business_id_b": ["Mexican", "Burgers", "Gastropubs & Wine"],
    "business_id_k": ["Automotive", "Delivery", "Whatever"]
    # 把你的海量数据都塞进来就行
}

2. 把标签转成数值向量

这里用TF-IDF最适合,因为它能衡量每个标签在整个数据集中的重要性,避免那些太常见的标签干扰聚类结果:

from sklearn.feature_extraction.text import TfidfVectorizer

# 把每个商家的标签列表转成空格分隔的字符串,方便向量器处理
texts = [" ".join(tags) for tags in business_data.values()]
# 初始化TF-IDF向量器,这里用lambda直接按空格拆分标签就行
vectorizer = TfidfVectorizer(tokenizer=lambda x: x.split())
# 生成每个商家的向量矩阵
X = vectorizer.fit_transform(texts)

3. 用K-means聚类,重点选对K值

K值选不好聚类结果会很离谱,推荐用肘部法则来找最优K:

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 测试不同K值的聚类效果
inertias = []
k_candidates = range(2, 10)  # 可以根据你的数据量调整范围
for k in k_candidates:
    kmeans = KMeans(n_clusters=k, random_state=42, n_init='auto')
    kmeans.fit(X)
    inertias.append(kmeans.inertia_)

# 画肘部图,找拐点对应的K就是最优值
plt.plot(k_candidates, inertias)
plt.xlabel("Number of Clusters (K)")
plt.ylabel("Inertia (Cluster Compactness)")
plt.title("Elbow Method to Find Optimal K")
plt.show()

比如图里拐点在K=3,那就用K=3训练最终模型:

optimal_k = 3  # 替换成你找到的最优K
kmeans = KMeans(n_clusters=optimal_k, random_state=42, n_init='auto')
cluster_labels = kmeans.fit_predict(X)

# 把商家ID和聚类结果对应起来,再按簇分组
from collections import defaultdict
clustered_businesses = defaultdict(list)
for business_id, cluster in zip(business_data.keys(), cluster_labels):
    clustered_businesses[cluster].append(business_id)

# 看看结果,顺便打印每个簇的核心标签,更直观
for cluster_id, businesses in clustered_businesses.items():
    print(f"Cluster {cluster_id}:")
    print(f"Businesses: {businesses}")
    # 找出该簇中心对应的Top3标签
    top_tag_indices = kmeans.cluster_centers_[cluster_id].argsort()[-3:][::-1]
    top_tags = [vectorizer.get_feature_names_out()[i] for i in top_tag_indices]
    print(f"Core Tags: {top_tags}\n")
三、通用文本K-means聚类的实现步骤

如果是处理更长的文本(比如商家评论、描述),步骤类似,但预处理要更细致:

1. 先做文本清洗

比如去标点、去停用词、词形还原,让文本更干净:

import re
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer

# 先下载nltk的停用词和词形还原数据(第一次运行需要)
# import nltk
# nltk.download('stopwords')
# nltk.download('wordnet')

stop_words = set(stopwords.words('english'))
lemmatizer = WordNetLemmatizer()

def clean_text(text):
    # 去掉特殊字符和数字
    text = re.sub(r'[^a-zA-Z\s]', '', text)
    # 全部转小写
    text = text.lower()
    # 分词后去除停用词+词形还原
    words = [lemmatizer.lemmatize(word) for word in text.split() if word not in stop_words]
    return " ".join(words)

# 示例:处理长文本
long_texts = [
    "This cozy Italian restaurant serves amazing wood-fired pizza and imported wine.",
    "Our gastropub offers juicy Mexican burgers and craft beer on tap."
]
cleaned_texts = [clean_text(text) for text in long_texts]

2. 文本向量化

还是用TF-IDF,要是文本量特别大,可以限制特征数量避免维度爆炸:

vectorizer = TfidfVectorizer(max_features=1000)  # 保留Top1000重要特征
X = vectorizer.fit_transform(cleaned_texts)

3. K-means聚类

和之前的步骤一样,用肘部法则选K,训练模型,然后分析结果就行。

额外小Tips
  • 如果你的标签有明显的层级关系(比如"Restaurant"是大类,"Mexican"是子类),可以先把每个标签转成Word2Vec向量,再对每个商家的所有标签向量取平均,用这个平均向量来聚类,这样能更好捕捉标签的语义关联。
  • K-means对初始中心敏感,sklearn 1.2+版本可以设置n_init='auto',让模型自动选最优初始中心,避免局部最优。

内容的提问来源于stack exchange,提问作者f_s

火山引擎 最新活动