zoukankan      html  css  js  c++  java
  • 基于AdaBoost的营销响应预测

    1. 案例背景

    通过数据预测下一次营销活动时,响应活动的会员名单和具体概率。

    数据:

    order.xlsx表: sheet1为训练集,sheet2为预测集

    特征变量数:13

    数据条数:训练集39999条,预测集8843条

    NA值:有

    异常值:有

    13个特征变量:

    age:年龄(整数型变量)

    total_pageviews:总页面浏览量(整数型变量)

    edu:教育程度(分类型变量,值域[1,10])

    edu_ages:受教育年限(整数型变量)

    user_level:用户等级(分类变量,值域[1,7])

    industry:用户企业划分(分类型变量,值域[1,15])

    value_level:用户价值度分类(分类型变量,值域[1,6])

    act_level:用户活跃度分类(分类型变量,值域[1,5])

    sex:性别(0或1)

    blue_money:蓝券金额(整数型变量)

    red_money:红券金额(整数型变量)

    work_hours:工作时间长度(整数型变量)

    region:地区(分类型变量,值域[1,41])

    2. 案例技术

    数据预处理:二值化标志转换OneHotEncoder、基于方差分析的特征选择的数据降维SelectPercentile结合f_classif

    数据建模:管道方法Pipe、交叉检验cross_val_score配合StratifiedKFold和自定义得分计算方法、集成分类算法AdaBoostClassifier

    主要用的库:time、Numpy、Pandas、Sklearn

    技术应用重点:通过管道方法将多个数据处理环节结合起来,形成处理管道对象,针对对象做交叉检验得到不同参数下的检验结果

    3. 案例过程

    步骤1:导入库

    """
    
    OneHotEncoder:将分类变量和顺序变量转换为二值化标志变量
    StratifiedKFold,cross_val_score:交叉验证,前者用来将数据分为训练集和测试集;后者用来交叉检验。
    StratifiedkFold 能结合样本标签做数据集分割,而不是完全的随机选择和分割
    SelectPercentile,f_classif:前者用来做特征选择的数量控制,后者用来确定特征选择的得分计算标准
    AdaBoostClassifier:集成算法,用来做分类模型训练
    Pipeline:将不同的环节结合起来(本案例中,将特征选择和集成算法结合起来形成一个”管道对象“,然后针对该对象
    训练不同参数下交叉检验的结果)
    
    
    """
    
    import time
    import numpy as np
    import pandas as pd
    from sklearn.preprocessing import OneHotEncoder         # 导入二值化标志转化库
    from sklearn.model_selection import StratifiedKFold, cross_val_score    # 导入交叉检验算法
    from sklearn.feature_selection import SelectPercentile, f_classif       # 导入特征选择方法
    from sklearn.ensemble import AdaBoostClassifier         # 导入集成算法
    from sklearn.pipeline import Pipeline                   # 导入Pipeline库
    from sklearn.metrics import accuracy_score              # 准确率指标

    步骤2:数据基本审查(基本状态审查,缺失值审查,类样本均衡审查)

    set_summary():

    1. 在format函数中,df的形状由于记录训练集 X 的特征数量,因此最后减 1。

    2. head():显示指定数量(N)的前N条数据。

    3. describe():显示数据最小值,均值,标准差,25%,50%,75%分位数,最大值。

    4. dtypes():显示所有列的数据类型。(为后面的数据类型转换做准备)

    na_summary():

    1. df.isnull().any():判断指定轴是否含有缺失值。

    2. df.count():统计每个特征非NA记录数。

    3. na_lines返回一个包含True/False的列表,使用sum()方法统计缺失值的数量。

    def set_summary(df):
    
        """
        查看数据
        :return:
        """
    
        print('Data Overview')
        print('Records: {0}	Dimension{1}'.format(df.shape[0], (df.shape[1]-1)))
    
        # 打印数据集 X 的形状
        print('-' * 30)
        print(df.head(2))       # 打印前两条数据
        print('-' * 30)
        print('Data DESC')
        print(df.describe())    # 打印数据描述信息
        print('Data Dtypes')
        print(df.dtypes)        # 打印数据类型
        print('-' * 60)
    
    
    
    def na_summary(df):
    
        """
        查看数据的缺失
        :param df:
        :return:
        """
    
        na_cols = df.isnull().any(axis=0)   # 每一列是否有缺失值
        print('NA Cols:')
        print(na_cols)                      # 查看具有缺失值的列
        print('valid records for each Cols:')
        print(df.count())                   # 每一列非NA的记录数
        na_lines = df.isnull().any(axis=1)  # 每一行是否有缺失值
        print('Total number of NA lines is: {0}'.format(na_lines.sum()))    # 查看缺失值的行总记录数
        print('-' * 30)
    
    
    
    def label_summary(df):
    
        """
        查看每个类的样本量分布
        :param df:
        :return:
        """
        print('Label sample count:')
        print(df['value_level'].groupby(df['respone']).count())     # 以response为分类汇总维度对value_level列计数统计
        print('-' * 60)
    

    步骤3:数据预处理

    type_con():转换目标列的数据为特定数据类型

    1. items():以列表返回可遍历的(键, 值) 元组数组。

    2. DataFrame.astype():将特定的列数据类型转换为另一种数据类型。不仅如此,还可以使用Python字典一次更改多个列类型。字典中的键与列名相对应,字典中的值与希望列属于的新数据类型相对应。

    def type_con(df):
    
        """
        转换目标列的数据为特定数据类型
        :param df:
        :return:
        """
    
        val_list = {'edu': 'int32',
                    'user_level': 'int32',
                    'industry': 'int32',
                    'value_level': 'int32',
                    'act_level': 'int32',
                    'sex': 'int32',
                    'region': 'int32'}      # 字典:定义要转换的列及其数据类型(key:列名,velue:新数据类型)
        for var, type in val_list.items():
            df[var] = df[var].astype(type)
        print('Data Dtypes:')
        print(df.dtypes)
        return df

    na_replce():将NA值替换

    def na_replace(df):
    
        """
        将NA值使用自定义方法得替换
        :param df:
        :return:
        """
    
        na_rules = {'age': df['age'].mean(),
                    'total_pageviews': df['total_pageviews'].mean(),
                    'edu': df['edu'].median(),      # median():中值
                    'edu_ages': df['edu_ages'].median(),
                    'user_level': df['user_level'].median(),
                    'industry': df['industry'].median(),
                    'act_level': df['act_level'].median(),
                    'sex': df['sex'].median(),
                    'red_money': df['red_money'].median(),
                    'region': df['region'].median()
                    }
        df = df.fillna(na_rules)        # 使用指定方法填充缺失值
        print('Check NA exists:')
        print(df.isnull().any().sum())  # 查看是否还有缺失值
        return df

    symbol_con():将分类和顺序变量转换为二值化的标志变量

    该函数做二值化的标志转换,主要用于将分类变量和顺序变量转换为二值化变量,值域为 0 和 1。

    在转换过程中,由于涉及训练集(及测试集)和预测集两种状态,训练集需要使用转换对象 fit 方法训练,然后使用训练好的模型分别对训练集和预测集做转换,因此需要区分不同阶段。

    具体实现过程:

    定义需转换的列形成数据框 df_con

    定义无需转换的列形成数据矩阵(数据框的值,通过values获得) df_org

    df_org 是 Numpy矩阵而非 Pandas 数据框,接下来使用 Numpy 方法做数据矩阵合并,原因是 OneHotEncoder 转换后的对象也是 Numpy 矩阵

    接下来根据train的状态做判断:

    为True时,用OneHotEncoder方法建立转换对象enc,然后用fit方法做训练,接着用transform方法做转换 (这里fit和transform方法分开操作是enc对象要在fit之后传给预测集使用) 最后将未转换的数据与转换后的数据合并。

    为False时,直接用训练阶段获得的对象enc做transform,然后将结果合并。

    def symbol_con(df, enc_object=None, train=True):
    
        """
        将分类和顺序变量转换为二值化的标志变量
        :param df:
        :param enc_object:
        :param train:
        :return:
        """
    
        convert_cols = ['edu', 'user_level', 'industry', 'value_level', 'act_level', 'sex', 'region']       # 选择要做标志转换的列(教育程度,用户等级,用户企业划分,用户价制度划分,用户活跃度划分,性别,地区)
        df_con = df[convert_cols]       # 选择要做标志转换的数据
        df_org = df[['age', 'total_pageviews', 'edu_ages', 'blue_money', 'red_money', 'work_hours']].values   # 设置不做标志转换的列(df.column.values:以array形式返回指定column的所有取值)
        if train == True:               # 如果数据处于训练阶段
            enc = OneHotEncoder()       # 建立标志转换模型对象
            enc.fit(df_con)             # 训练模型
            df_con_new = enc.transform(df_con).toarray()    # 转换数据并输出为数组格式
            new_matrix = np.hstack(df_con_new, df_con)      # 将未转换的数据与转换后的数据合并
            return new_matrix, enc
        else:
            df_con_new = enc_object.transform(df_con).toarray()     # 使用训练阶段获得转换对象转换数据并输出数组格式
            new_matrix = np.hstack((df_con_new, df_org))    # 将未转换的数据与转换的数据合并
            return new_matrix

    1. enc_transform:Sklearn的标志转换对象,该对象只有应用fit方法后才形成,因此训练阶段为空;在预测集应用阶段,直接使用该参数传入训练集时的对象即可。

    2. train:判断是否为训练阶段,训练阶段为True,预测阶段为False。根据不同的状态判断是否需要做 fit,并返回不同的参数对象。

    get_best_model():获得最佳模型参数

    在该函数中,通过交叉检验的方法,自定义几种不同的检验指标,从中找到比较合适的参数。

  • 相关阅读:
    kvm克隆虚拟机
    vSAN添加license
    KVM虚拟机快照
    第二次作业及总结——数据类型和运算符
    第二次作业心得
    做完c语言作业的心得
    介绍自己
    awk数组 Jazz
    Java入门第一阶段总结
    区间dp入门+例题
  • 原文地址:https://www.cnblogs.com/keye/p/12751372.html
Copyright © 2011-2022 走看看