如何用机器学习挖掘无目标变量的客户画像模式?
客户画像挖掘:无目标变量下的方法选择
问题说明
我手上有某虚构企业购买客户的个人特征数据集,没有目标变量,只有客户特征字段。我的目标是挖掘客户画像模式,但这个模式不一定是各列中出现最频繁的特征。想问问能不能用RandomForest实现?或者有没有更合适的技术?
数据集结构
所有列均为object格式,部分缺失值用'Blank'表示:
Date Name Salary Position Age '05/10/2023' 'Daniel' '10,000' 'IT' 32 '05/12/2024' 'John' '9,000' 'Blank' 27 '03/01/2023' 'Niel' 'Blank' 'Data Scients' 21 '03/01/2023' 'Isa' '10,000' 'Engineer' 51 '05/10/2023' 'Ana' '11,000' 'Data Scients' 52 '05/12/2024' 'Ian' '9,500' 'Doctor' 48 '03/01/2023' 'Fred' 'Blank' 'IT' 21 '03/01/2023' 'Carol' '15,000' 'Blank' 30
期望输出
希望得到明确的标准客户画像,格式类似:
The most standard profile is: Salary x, Position y, and Age z.
已尝试的聚类方法
我试过用KMeans聚类,但觉得效果不好——比如薪资输出只是简单均值,不能体现真实的模式。我想要的是一个不一定真实存在、但基于各变量(薪资、职位、年龄)内在模式构建的画像。尝试的代码如下:
# Encode categorical variables df['Position'] = pd.Categorical(df['Position']).codes # Perform clustering kmeans = KMeans(n_clusters=1, random_state=42) kmeans.fit(df[['Salary', 'Position', 'Age']]) # Get the centroid of the cluster centroid = kmeans.cluster_centers_[0]
想问问有没有更优的方法?NLP或RandomForest可行吗?
解决方案与分析
1. RandomForest的适用性
传统RandomForest是监督学习算法,必须依赖目标变量(比如客户是否复购)才能训练,你现在没有目标变量,直接用不了。但可以用它的无监督变体:
- 无监督随机森林(Unsupervised Random Forest):通过随机森林计算样本间的相似度(proximity矩阵),再基于这个矩阵做层次聚类。之后对每个簇的特征做统计(类别型取众数、数值型取中位数),能捕捉非线性的特征关联,比传统聚类更灵活。
2. 更适合的替代方法
(1)关联规则挖掘(Apriori/FPGrowth)
这是无标签数据下找特征组合模式的绝佳方法,能找出“薪资中等 + 职位IT + 年龄青年”这类有意义的特征组合,而不是单一列的众数或均值。
- 步骤:先把连续变量(薪资、年龄)离散化分档,把'Blank'作为独立类别,然后用Apriori挖掘频繁项集,再筛选置信度高的规则,提取核心特征组合作为画像。
- 示例代码:
import pandas as pd from mlxtend.frequent_patterns import apriori, association_rules # 构造数据集 data = [ ['05/10/2023', 'Daniel', '10,000', 'IT', 32], ['05/12/2024', 'John', '9,000', 'Blank', 27], ['03/01/2023', 'Niel', 'Blank', 'Data Scients', 21], ['03/01/2023', 'Isa', '10,000', 'Engineer', 51], ['05/10/2023', 'Ana', '11,000', 'Data Scients', 52], ['05/12/2024', 'Ian', '9,500', 'Doctor', 48], ['03/01/2023', 'Fred', 'Blank', 'IT', 21], ['03/01/2023', 'Carol', '15,000', 'Blank', 30] ] df = pd.DataFrame(data, columns=['Date', 'Name', 'Salary', 'Position', 'Age']) # 数据预处理 df['Salary'] = df['Salary'].replace('Blank', pd.NA).str.replace(',', '').astype(float) # 薪资分档:低/中/高 df['Salary_bin'] = pd.cut(df['Salary'], bins=[0, 9000, 12000, float('inf')], labels=['Low', 'Medium', 'High']) # 年龄分档:青年/中年/老年 df['Age_bin'] = pd.cut(df['Age'], bins=[0, 30, 45, float('inf')], labels=['Young', 'Middle', 'Senior']) # 缺失职位标记为Unknown df['Position'] = df['Position'].replace('Blank', 'Unknown') # 转换为关联规则所需的one-hot格式 assoc_data = pd.get_dummies(df[['Salary_bin', 'Position', 'Age_bin']].astype(str)) # 挖掘频繁项集(最小支持度0.2) frequent_itemsets = apriori(assoc_data, min_support=0.2, use_colnames=True) # 生成高置信度规则(最小置信度0.7) rules = association_rules(frequent_itemsets, metric="confidence", min_threshold=0.7) # 筛选包含三个特征的高频项集,按支持度排序 top_profile = frequent_itemsets[frequent_itemsets['itemsets'].apply(lambda x: len(x)==3)].sort_values('support', ascending=False).iloc[0] print(f"The most standard profile is: {', '.join([item.split('_')[1] if '_' in item else item for item in top_profile['itemsets']])}")
(2)基于密度的聚类(DBSCAN)+ 特征统计
替代KMeans,DBSCAN对离群点不敏感,能找到密度相连的真实簇。之后对每个簇的特征用**众数(类别型)+ 中位数(数值型)**统计,避免均值被极端值拉偏:
- 步骤:清洗数据(Blank转NaN、薪资转数值),标准化数值变量,用DBSCAN聚类,然后对每个簇的职位取众数、薪资和年龄取中位数,得到簇的典型画像,选择最大的簇作为标准画像。
3. NLP的适用性
你的数据都是结构化的类别/数值字段,没有自由文本(比如客户评论、反馈),NLP在这里没有用武之地,完全没必要用。
内容的提问来源于stack exchange,提问作者Heloisa Ramos
相关产品推荐
相关产品推荐

