基于聚类算法与随机森林算法的手机终端换机推荐

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 

1. 项目背景

        随着用户数据量的激增,传统的数据分析方法和营销方式受到巨大的挑战,急需对海量数据进行深度挖掘, 探索用户消费行为数据的潜在价值。本项目对原有的推荐模型进行优化,基于品牌的性能,价格及用户使用信息,对用户实行换机预测并推荐倾向的终端应用。通过模型对用户换机时机进行预测,并推荐终端模型,换机预测模型运用随机森林算法对数据进行预测,终端偏好推荐模型通过聚类算法,对用户群体进行分类,最终对模型进行输出,总结偏好分析和聚类结果,构造终端选择升级对照库和热机库,对推荐目标机型进行排序获得结果。

2. 功能组成

        基于聚类算法与随机森林算法的手机终端换机推荐系统的功能主要包括:

3. 数据读取与预处理

3.1 依赖包导入和数据读取

        导入数据分析所需要的依赖包:

%%time
import os
import gc
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt
from IPython.display import display
np.random.seed(7)
plt.style.use('fivethirtyeight')
from tqdm import tqdm

import warnings
warnings.filterwarnings('ignore')

from matplotlib.font_manager import FontProperties
# 读取字体路径,设置字体为思源黑体
myfont=FontProperties(fname=r'/System/Library/Fonts/Hiragino Sans GB.ttc')
sns.set(font=myfont.get_name())

        本项目采用某电信服务商近一年的用户终端换机数据,每个月为一个csv文件,pandas读取后,进行数据的拼接:

month_df = pd.concat([month1_df, month2_df, month3_df, month4_df, month5_df, month6_df, 
                      month7_df, month8_df, month9_df, month10_df, month11_df, month12_df], axis=0)

del month1_df, month2_df, month3_df, month4_df, month5_df, month6_df
del month7_df, month8_df, month9_df, month10_df, month11_df, month12_df

3.2 数据缺失值分析和填充

def contains_null(dataframe):
    missing_df = dataframe.isnull().sum(axis=0).reset_index()
    missing_df.columns = ['column_name', 'missing_count']
    missing_df['missing_rate'] = 1.0 * missing_df['missing_count'] / dataframe.shape[0]
    missing_df = missing_df[missing_df.missing_count > 0]
    missing_df = missing_df.sort_values(by='missing_count', ascending=False)
    return missing_df

contains_null(month_df)
column_namemissing_countmissing_rate
6终端品牌3835680.063928
7终端型号3835660.063928
5ARPU值段606420.010107
8流量使用量19400.000323

        可以看出,部分字段存在一定的缺失情况,对于类别型特征,按照众数进行缺失值填充:

# “ARPU值段” 字段填充为众数 ’0-49‘
month_df['ARPU值段'].fillna("0-49", inplace = True) 
month_df['流量使用量'].fillna("0-499", inplace = True) 
# 对于终端型号缺失的用户数据需要删除,由于需要判断用户是否换机,终端型号不可缺失
month_df.dropna(inplace=True)

3.3 异常值去除

user_month_df = month_df.groupby('IMSI').count().reset_index()

# 对于数据记录存在月份缺失的用户,进行删除
drop_users = set(user_month_df[user_month_df['月份'] != 12]['IMSI'].values.tolist())
print('存在 {} 异常用户的数据缺失部分月份,这类用户进行删除'.format(len(drop_users)))

month_df['drop'] = month_df['IMSI'].map(lambda x: x in drop_users)
month_df = month_df[month_df['drop'] != True]
del month_df['drop']

        完成预处理后的数据集如下,数据集一共包含 466986 个用户,5603832 条记录:

4. 数据探索式分析

4.1 使用手机的用户的性别、网别的分布

        可以看出,本次数据中使用手机的男性较多,并且存在少量性别缺失的数据,对于此类缺失值,考虑填充为性别出现最多的男性。

4.2 用户的年龄值段、ARPU值段(每用户平均收益)的分布情况 

4.3 用户使用手机的终端品牌的分布情况

brand_df = month_df['终端品牌'].value_counts().reset_index()
brand_df.columns = ['终端品牌', 'Count']
print('手机品牌数:', brand_df.shape[0])
brand_df.head()

print(brand_df['终端品牌'].values.tolist()[:100])
手机品牌数: 2258
['Apple', 'Samsung', '苹果', 'Nokia', '三星', 'Xiaomi', 'Lenovo', 'HUAWEI', '小米', '华为', '**', 'HTC', 'Coolpad', 'OPPO', 'NOT KNOWN', '联想', '诺基亚', 'BBK', 'ZTE', '欧珀', 'Gionee', 'Motorola', '宇龙', '宏达', '微软', 'EMULATIONAL', 'K-Touch', 'LG', 'Sony', 'SonyEricsson', 'Meizu', '中兴', '步步高', 'TCL', 'Cinterion', '金立', '魅族', 'Basicom', '维沃', 'Daxian Pantech', '索尼', 'Bifer', '摩托罗拉', 'Hisense', 'CINTERION', 'AOLE', 'AUX', 'Bird', 'Sharp', 'ETON', 'Haier', '酷派', 'HUAWEI TECHNOLOGY', 'Pioneer', 'Wellphone', 'CECT', 'Telsda', '索尼爱立信', 'F-FOOK', '浪潮乐金', 'Vogo', 'ARES', 'Sunup', '天宇朗通', '宝捷讯', 'Hedy', 'NOTKNOWN', '贝尔丰', 'OUKI', 'Noain', 'OPSSON', 'SICT', 'OZZO', '海信', 'ChangHong', 'Boway', 'Jugate', 'Koobee', 'Blackberry', 'SanCup', '亿通', 'SAGA', 'ECETD', 'Konka', '大显泛泰', '海尔', 'SangFei', '奥乐', 'ASUS', 'TETC', 'Doov', '奥克斯', 'Forme', 'HOSIN', '酷乐', 'AMOI', 'SOP', 'EBEST', '沃歌', 'Elitek']

        可以看出,手机品牌多达 2280 个!且有的手机品牌是同一个品牌,只是中英文不同的表达,如 苹果和Apple。因此需要做数据归一化处理!

plt.figure(figsize=(16, 5))
plt.subplot(121)
plt.scatter(range(brand_df.shape[0]), brand_df['Count'])

plt.subplot(122)
tmp = brand_df[brand_df['Count'] > 50000]
plt.scatter(range(tmp.shape[0]), tmp['Count'])
plt.show()

print('终端品牌个数大于 50000 的有 {} 种'.format(tmp.shape[0]))

        终端品牌个数大于 50000 的有 15 种,手机品牌个数呈现严重的长尾分布,将品牌数小于一定阈值的手机设置为’其他‘类别。

4.4 终端型号的分布情况 

        可以看出,终端型号个数大于 10000 的有 50 种,需要注意的是,此处不能对终端型号进行类似出现次数少于一定阈值设置为其他的操作,因为需要根据终端型号的变化情况,决定用户是否进行了换机行为!

4.5 流量使用量、语音通话时长、短信条数的分布情况

plt.figure(figsize=(16, 5))
plt.subplot(121)
tmp = month_df[month_df['语音通话时长'] < 2500]
sns.distplot(tmp['语音通话时长'], bins=50, color='red')
plt.title('语音通话时长的密度分布直方图', fontsize=16, weight='bold')

plt.subplot(122)
tmp = month_df[(month_df['短信条数'] > 0) & (month_df['短信条数'] < 1000)]
sns.distplot(tmp['短信条数'], bins=50, color='blue')
plt.title('短信条数的密度分布直方图', fontsize=16, weight='bold')
plt.show()

5. 终端推荐机器学习建模

        利用用户 1 - 11 月份的终端使用记录数据,预测第十二月份是否会换机,以及换机的概率。选择 10000 个用户作为训练集、2500 个的用户作为验证集,2500 个用户数据作为测试集。

train_users, valid_users, test_users = all_users[:10000], all_users[10000:12500], all_users[12500:15000]

print('训练集个数:', len(train_users))
print('验证集个数:', len(valid_users))
print('测试集个数:', len(test_users))

5.1 特征工程

# 将类别特征进行 one-hot 编码
net_type_df = pd.get_dummies(month_df['网别'], prefix='网别')
month_df = pd.concat([month_df, net_type_df], axis=1)
del month_df['网别']

sex_df = pd.get_dummies(month_df['性别'], prefix='性别')
month_df = pd.concat([month_df, sex_df], axis=1)
del month_df['性别']

# 将字符类型且存在大小顺序的特征进行 labelencoder 编码
from sklearn.preprocessing import LabelEncoder

encoder = LabelEncoder()
month_df['年龄值段'] = encoder.fit_transform(month_df['年龄值段'])
month_df['ARPU值段'] = encoder.fit_transform(month_df['ARPU值段'])
month_df['流量使用量'] = encoder.fit_transform(month_df['流量使用量'])

# 对于终端品牌、终端型号类型的特征,由于不同的终端品牌和型号众多,不适合 One-hot 编码,也采用 labelencoder 编码
month_df['终端品牌'] = encoder.fit_transform(month_df['终端品牌'])
month_df['终端型号'] = encoder.fit_transform(month_df['终端型号'])

        可以看出,编码后的数据不包含字符串类型的类别特征,均编码成了模型可处理的数值类型的特征。

        基于用户历史的换机行为时间序列数据,构造其他特征,受篇幅限制,此处省略。

        训练集中换机的用户占 0.0951,有 951 个用户 验证集中换机的用户占 0.0912,有 228 个用户 测试集中换机的用户占 0.1024,有 256 个用户。

5.2 聚类算法和随机森林算法对用户终端换机进行分析建模

plt.figure(figsize=(16, 6))
plt.bar(['聚类 Train F1', '随机森林 Train F1', '聚类 Valid F1', '随机森林 Valid F1', '聚类 Test F1', '随机森林 Test F1'], 
        [ktrain_f1, rtrain_f1, kvalid_f1, rvalid_f1, ktest_f1, rtest_f1])
plt.show()

5.3 对预测结果进行可视化

可以看出:

  • 随机森林模型预测效果相比聚类算法效果要好
  • 测试集的 F1 值指标为 0.8083-0.9068,结果TSNE聚类后,红色为终端换机的用户,可以看出模型预测效果较好!

6. 总结

        本项目对原有的推荐模型进行优化,基于品牌的性能,价格及用户使用信息,对用户实行换机预测并推荐倾向的终端应用。通过模型对用户换机时机进行预测,并推荐终端模型,换机预测模型运用随机森林算法对数据进行预测,终端偏好推荐模型通过聚类算法,对用户群体进行分类,最终对模型进行输出,总结偏好分析和聚类结果,构造终端选择升级对照库和热机库,对推荐目标机型进行排序获得结果。

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。技术交流、源码获取认准下方 CSDN 官方提供的学长 QQ 名片 :)

精彩专栏推荐订阅:

1. Python 毕设精品实战案例
2. 自然语言处理 NLP 精品实战案例
3. 计算机视觉 CV 精品实战案例

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python极客之家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值