**

通过TalkingData用户行为数据预测性别(基于决策树算法)

**

要求如下

一、案例数据:

TalkingData是中国最大的独立第三方移动数据服务平台,平均月活跃用户为6.5亿,为超过12万款移动应用,以及10万应用开发者提供服务。案例数据集来自TalkingData,已进行脱敏处理。目标是通过用户的移动应用使用情况、位置信息和移动设备信息,预测用户性别。精确预测用户性别有助于开发者和广告商推送用户感兴趣的内容。

案例共包含6个数据集:

• 数据集gender_age:每个用户对应一个设备号(变量device_id),需要预测用户性别(变量gender);

• 数据集events和app_events:用户数据上传事件时的经纬度和时间戳,以及事件对应的应用(变量app_id)列表;

• 数据集app_labels和label_categories:应用对应的分类标签(变量label_id)和分类描述(变量category);

• 数据集phone_brand_device_model:用户使用的手机品牌(变量phone_brand)和型号(变量device_model)。

每个数据集包含的变量和相互之间的连接关系如下图所示。

给性别加索引 添加性别数据特征_数据集


二、数据预处理和特征工程

目标:连接相关数据,并找出与预测用户性别相关联的属性

三、模型训练
使用最优的超参数组合在训练集上做模型训练,并画出最终的决策树。

四、模型评估
在测试集上做模型测试,评估模型性能(accuracy, F1, AUC)。

**

解决方式如下

**
一、导入数据
使用pandas库中的pd.read_csv(“文件存放路径”)
按照要求合并表,可以使用pandas库中的merge方法:pd.merge(table1,table2)将表格合并。
(由于此处没有对表格的链接方式作要求,故仅使用pd.merge(table1,table2)即可)

Tips:对于导入数据内存不够报错的同学可以考虑

二、数据探索和可视化:
数据类型
使用dataframe.info()获取数据描述,

给性别加索引 添加性别数据特征_数据_02


如上图所示,由于数据值过大,占用内存多达9.4G,因此需要对数据进行处理,将部分数值较小的数据的类型从int 64/float 64 转至 int 8/float 16。

三、数据清洗和补全
(1)由dataframe.info()可以看出此数据集中是否有空值。
(2)由于决策树模型对于数据中包含的类别较为敏感,当数据类别极多时,考虑去除该列以简化模型,因此计算各列数据的总类别数,以此判断是否将该列列入决策树模型的考虑当中。
由于数据中有标称型属性,计算该属性的类别,可以使用pd.dataframe.unique()方法返回数据中所有不重复的项,并用tolist()将其转换成列表,计算该列表的长度即得该列数据类别总数。
即len(dataframe[列名].unique().tolist())
去除类别过多的列数据,使用dataframe.drop(columns = 列名或存放列名的列表,axis = 1)

Tips: axis = 1删除该列,axis = 0删除该行,默认axis = 0

四、数据预处理:
由于数据中有标称型属性,因此需要对数据进行处理。
pd.dataframe.unique()方法返回数据中所有不重复的项,并用tolist()将其转换成列表。index() 函数用于从列表中找出某个值第一个匹配项的索引位置。如此即可将标称型数据转和数值0,1,2,3…一一对应。

lables = dataframe[列名].unique().tolist()
dataframe[列名]= dataframe[列名].apply(lambda n: lables.index(n))

五、建模

六、Jupyter notebook代码

#%%
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sklearn
from sklearn.tree import tree, DecisionTreeClassifier
from sklearn.model_selection import StratifiedKFold
import graphviz
from sklearn import metrics
from sklearn.metrics import auc


#%%

# 导入csv文件

app_events_data = pd.read_csv("F:/txy/demo/app_events.csv")
app_labels_data = pd.read_csv("F:/txy/demo/app_labels.csv")
events_data = pd.read_csv("F:/txy/demo/events.csv")
gender_age_data = pd.read_csv("F:/txy/demo/gender_age.csv")
label_categories_data = pd.read_csv("F:/txy/demo/label_categories.csv")
phone_brand_device_model_data = pd.read_csv("F:/txy/demo/phone_brand_device_model.csv")
print("Data have been imported!")

#%%

tabel_list = [phone_brand_device_model_data,gender_age_data,events_data,app_events_data,app_labels_data,label_categories_data]
tabel_list_name = ['phone_brand_device_model_data','gender_age_data','events_data','app_events_data','app_labels_data','label_categories_data']

customer_data = tabel_list[0]
for tabel_list_index in range(1,len(tabel_list)):
    customer_data = pd.merge(customer_data,tabel_list[tabel_list_index])
# 释放内存
for list in tabel_list:
    del list
print("Data have been merged.")

#%%

customer_data.info()

#%%

# 处理gender,phone_brand,device_model,category字符型数据
reform_data_list = ['gender','phone_brand','device_model','category','group']
for reform_data in reform_data_list:
    lables = customer_data[reform_data].unique().tolist()
    print("Labels of "+reform_data +" is {}".format(len(lables)))
#%%    
reform_data_int8_list = ['gender','phone_brand','group']
for reform_data in reform_data_int8_list:
    lables = customer_data[reform_data].unique().tolist()
    customer_data[reform_data] = customer_data[reform_data].apply(lambda n: lables.index(n)).astype(pd.np.int8)
reform_data_int16_list = ['device_model','category']
for reform_data in reform_data_int16_list:
    lables = customer_data[reform_data].unique().tolist()
    customer_data[reform_data] = customer_data[reform_data].apply(lambda n: lables.index(n)).astype(pd.np.int16)
#%%
customer_data.info()
#%%
small_data_list = ['age','is_installed','is_active']
for small_data in small_data_list:
    customer_data[small_data] = customer_data[small_data].astype(pd.np.int8)

#%%
customer_data.info()
#%%

giant_data_list = ['device_id','longitude','latitude','app_id','label_id']
for giant_data in giant_data_list:
    lables = customer_data[giant_data].unique().tolist()
    print("Labels of "+giant_data +" is {}".format(len(lables)))
#%%    
lables = customer_data['label_id'].unique().tolist()
customer_data['label_id'] = customer_data['label_id'].apply(lambda n: lables.index(n)).astype(pd.np.int16)

#%%
data_to_be_dropped = ['device_id','longitude','latitude','app_id','timestamp','event_id']
for data in data_to_be_dropped:
    customer_data = customer_data.drop(labels = data, axis=1)
customer_data.info()
#%%
feature = customer_data.drop('gender',1).columns[:]
class_name = np.unique(gender_age_data['gender'])
X = customer_data.drop('gender',1).values
y = customer_data[['gender']].values
dtc = DecisionTreeClassifier(max_depth=3,min_samples_leaf=1)
skf=StratifiedKFold(n_splits=3)
overall_accuracy = 0
overall_AUC = 0
count = 1
for train_index,test_index in skf.split(X,y):
    X_train,X_test=X[train_index],X[test_index]
    y_train,y_test=y[train_index],y[test_index]
    dtc = dtc.fit(X_train,y_train)
    prediction = dtc.predict(X_test)
    accuracy = dtc.score(X_test,y_test)
    print("The accuracy of the testset "+str(count)+" is: "+str(accuracy))
    fpr, tpr, thresholds = metrics.roc_curve(y_true = y_test, y_score= prediction,  pos_label=1)
    plt.plot(fpr,tpr,marker = 'o')
    plt.show()
    AUC = auc(fpr, tpr)
    print("The AUC of this prediction is "+str(AUC))
    dot_data = sklearn.tree.export_graphviz(dtc, out_file=None,
                         feature_names=feature,
                         class_names=class_name)
    graph = graphviz.Source(dot_data) 
    graph.render("tree" + str(count))
    overall_accuracy += accuracy
    overall_AUC += AUC
    count += 1
print("The overall accuracy is: "+str(overall_accuracy/3))
print("The overall AUC is: "+str(overall_AUC/3))