Scikit-learn中K-Means适配Levenshtein距离的变通方案咨询
针对含姓名文本特征的K-Means适配方案
方案1:预计算自定义距离矩阵,直接喂给K-Means
Scikit-learn的KMeans支持传入预计算的距离矩阵(需设置metric='precomputed'),可以直接绕开“全浮点特征”的限制,复用你已有的自定义距离函数。
步骤如下:
- 初始化你的自定义距离函数
- 预计算所有样本间的对称距离矩阵(对角线为0)
- 初始化KMeans时指定
metric='precomputed',传入距离矩阵完成聚类
代码示例:
from scipy.spatial.distance import cdist import numpy as np from sklearn.cluster import KMeans # 初始化自定义距离函数(假设text_feat是姓名特征列名列表,num_feat是数值特征列名列表) distance_func = distance_fun(tranches_transformed, text_feat=['姓名'], num_feat=[你的数值特征列名]) # 预计算所有样本间的距离矩阵 dist_matrix = cdist(tranches_transformed.values, tranches_transformed.values, metric=distance_func) # 基于预计算距离矩阵运行K-Means kmeans = KMeans(n_clusters=你的聚类数, metric='precomputed', n_init='auto') kmeans.fit(dist_matrix)
方案2:将姓名文本转为适配K-Means的数值特征
把姓名文本通过字符级编码转成浮点向量,和原有的数值/OHE特征拼接,让KMeans可以直接处理,同时保证同名样本向量完全一致、相似姓名向量距离接近。
最适配姓名场景的是字符n-gram编码,提取姓名的连续字符组合生成TF-IDF向量:
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans import numpy as np # 拆分特征:姓名列 + 其他浮点/OHE列 name_col = tranches_transformed.iloc[:, 0] other_features = tranches_transformed.iloc[:, 1:] # 字符n-gram编码姓名:提取2-3个连续字符的组合 vectorizer = TfidfVectorizer(analyzer='char', ngram_range=(2,3)) name_vec = vectorizer.fit_transform(name_col).toarray() # 标准化数值特征(OHE特征无需标准化) scaler = StandardScaler() other_scaled = scaler.fit_transform(other_features) # 拼接所有特征 combined_features = np.hstack([name_vec, other_scaled]) # 运行K-Means kmeans = KMeans(n_clusters=你的聚类数, n_init='auto') kmeans.fit(combined_features)
这种方式下,同名姓名会生成完全相同的TF-IDF向量,相似姓名(如“张三”和“张三丰”)的向量距离会远小于无关姓名,符合你的聚类需求。
方案3:换用支持混合类型的聚类工具
如果不想改动特征或距离矩阵,可以选择支持自定义距离、兼容混合数据类型的聚类算法,比如HDBSCAN(支持传入自定义距离函数),不过需要额外安装对应依赖库。
内容的提问来源于stack exchange,提问作者Chapo
相关产品推荐
相关产品推荐

