精华内容
下载资源
问答
  • 参赛队伍需要通过数据挖掘技术和机器学习算法,构建用户购买商家中相关品类的预测模型,输出用户和店铺、品类的匹配结果,为精准营销提供高质量的目标群体。同时,希望参赛队伍通过本次比赛,挖掘数据背后潜在的意义...

    前言

            偶然间在群里看到有人发了这个比赛,查了一下才知道这是京东举行的第三届JDATA算法大赛,可我从来没有听说过,有种被时代抛弃的感觉😢。我自从2016年参加了阿里天池的几个比赛之后就没有关注过这方面,一是工作比较忙,二是自己变懒了,唉。听说腾讯每年也举办什么广告算法大赛,感兴趣的同学可以参加一下,此外还有kaggle等等。这次比赛也只是打了个酱油,毕竟工作了,没有上学时那么多时间,而且现在的同学都太厉害了😆。虽然成绩不怎么样(89/1401),但我觉得这个流程还是值得记录和分享一下的。需注意的是,特征工程决定上限,而其余步骤只是逼近这个上限。最后,期待大佬们的分享~

    赛题介绍

    赛题:https://jdata.jd.com/html/detail.html?id=8
    数据:https://download.csdn.net/download/dr_guo/11207507
    在这里插入图片描述
    赛题背景

    京东零售集团坚持“以信赖为基础、以客户为中心的价值创造”这一经营理念,在不同的消费场景和连接终端上,在正确的时间、正确的地点为3亿多活跃用户提供最适合的产品和服务。目前,京东零售集团第三方平台签约商家超过21万个,实现了全品类覆盖,为维持商家生态繁荣、多样和有序,全面满足消费者一站式购物需求,需要对用户购买行为进行更精准地分析和预测。基于此,本赛题提供来自用户、商家、商品等多方面数据信息,包括商家和商品自身的内容信息、评论信息以及用户与之丰富的互动行为。参赛队伍需要通过数据挖掘技术和机器学习算法,构建用户购买商家中相关品类的预测模型,输出用户和店铺、品类的匹配结果,为精准营销提供高质量的目标群体。同时,希望参赛队伍通过本次比赛,挖掘数据背后潜在的意义,为电商生态平台的商家、用户提供多方共赢的智能解决方案。

    01 /评分

    参赛者提交的结果文件中包含对所有用户购买意向的预测结果。对每一个用户的预测结果包括两方面:
    (1)该用户2018-04-16到2018-04-22是否对品类有购买,提交的结果文件中仅包含预测为下单的用户和品类(预测为未下单的用户和品类无须在结果中出现)。评测时将对提交结果中重复的“用户-品类”做排重处理,若预测正确,则评测算法中置label=1,不正确label=0。
    (2)如果用户对品类有购买,还需要预测对该品类下哪个店铺有购买,若店铺预测正确,则评测算法中置pred=1,不正确pred=0。
    对于参赛者提交的结果文件,按如下公式计算得分:score=0.4F11+0.6F12
    此处的F1值定义为:
    在这里插入图片描述
    其中:Precise为准确率,Recall为召回率; F11 是label=1或0的F1值,F12 是pred=1或0的F1值。

    02 /赛题数据

    2.1 训练数据
    提供2018-02-01到2018-04-15用户集合U中的用户,对商品集合S中部分商品的行为、评价、用户数据。
    2.2 预测数据
    提供 2018-04-16 到 2018-04-22 预测用户U对哪些品类和店铺有购买,用户对品类下的店铺只会购买一次。
    2.3 数据表说明
    在这里插入图片描述

    1)行为数据(jdata_action)
    在这里插入图片描述
    2)评论数据(jdata_comment)
    在这里插入图片描述
    3)商品数据(jdata_product)
    在这里插入图片描述
    4)商家店铺数据(jdata_shop)
    在这里插入图片描述
    5)用户数据(jdata_user)
    在这里插入图片描述

    03 /任务描述及作品要求

    3.1 任务描述
    对于训练集中出现的每一个用户,参赛者的模型需要预测该用户在未来7天内对某个目标品类下某个店铺的购买意向。

    3.2 作品要求
    提交的CSV文件要求如下:

    1. UTF-8无BOM格式编码;
    2. 第一行为字段名,即:user_id,cate,shop_id(数据使用英文逗号分隔)
      其中:user_id:用户表(jdata_user)中用户ID;cate:商品表(jdata_product)中商品sku_id对应的品类cate ;shop_id:商家表(jdata_shop)中店铺ID;
    3. 结果不存在重复的记录行数,否则无效;
      对于预测出没有购买意向的用户,在提交的CSV文件中不要包含该用户的信息。
      提交结果示例如下图:
      在这里插入图片描述

    步骤汇总

    这是我自己总结的流程,如有不对,欢迎交流指正。

    1.查看分析数据

    2.数据清洗

    3.构造数据集(特征工程)

    开始自己选的特征连0.03都上不去,后来看到Cookly 洪鹏飞开源的baseline,我基于他写的删了很多特征又加了一点特征,分数可能都没有他的baseline高,但没办法,笔记本跑不动。我测试了一下我的笔记本最高只能处理300维,说到这我要吐槽一下京东了,能不能跟阿里一样提供开发环境,我好多想法受限于硬件无法实现。
    在这里插入图片描述
    下面是代码,需要注意的是,我构造了三个数据集,分别是训练集、测试集和预测集。预测集这个大家可能没有听说过,因为往往都叫测试集,但我觉得这样叫有点乱,所以给它起了个名叫预测集,专门用来预测最终结果。测试集也有点不一样,测试集应与训练集完全不相关,用来评估模型的表现,而且用的次数不能太多。理论上讲,模型在测试集的表现与在预测集上的表现应该是差不多的。此外,训练集也可以划分为训练集和验证集,但是很多时候都没有真正的测试集,而是把训练集划分为训练集和测试集或是划分为训练集、验证集和测试集。是不是感觉有点乱,我说的也不一定对,但只需记住一点,我们只用测试集去评估模型的表现,并不会去调整优化模型,慢慢体会吧。

    import pandas as pd
    import os
    import pickle
    import datetime
    import re
    import numpy as np
    
    jdata_action_file_dir = "../../jdata/jdata_action.csv"
    jdata_comment_file_dir = "../../jdata/jdata_comment.csv"
    jdata_product_file_dir = "../../jdata/jdata_product.csv"
    jdata_shop_file_dir = "../../jdata/jdata_shop.csv"
    jdata_user_file_dir = "../../jdata/jdata_user.csv"
    
    # 减少内存使用
    def reduce_mem_usage(df, verbose=True):
        numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
        start_mem = df.memory_usage().sum() / 1024 ** 2
        for col in df.columns:
            col_type = df[col].dtypes
            if col_type in numerics:
                c_min = df[col].min()
                c_max = df[col].max()
                if str(col_type)[:3] == 'int':
                    if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                        df[col] = df[col].astype(np.int8)
                    elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                        df[col] = df[col].astype(np.int16)
                    elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                        df[col] = df[col].astype(np.int32)
                    elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                        df[col] = df[col].astype(np.int64)
                else:
                    if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                        df[col] = df[col].astype(np.float16)
                    elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                        df[col] = df[col].astype(np.float32)
                    else:
                        df[col] = df[col].astype(np.float64)
        end_mem = df.memory_usage().sum() / 1024 ** 2
        if verbose:
            print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))
        return df
    
    # 行为数据
    jdata_action = reduce_mem_usage(pd.read_csv(jdata_action_file_dir))
    jdata_action.drop_duplicates(inplace=True)
    del jdata_action['module_id']
    
    # 视B榜数据而定,是否删除购物车记录(A榜数据只有8号后的购物车记录)
    jdata_action = jdata_action[-jdata_action['type'].isin([5])]
    
    # 评论数据
    # jdata_comment = reduce_mem_usage(pd.read_csv(jdata_comment_file_dir))
    
    # 商品数据
    jdata_product = reduce_mem_usage(pd.read_csv(jdata_product_file_dir))
    
    # 商家店铺数据
    jdata_shop = reduce_mem_usage(pd.read_csv(jdata_shop_file_dir))
    
    # 用户数据
    jdata_user = reduce_mem_usage(pd.read_csv(jdata_user_file_dir))
    
    Mem. usage decreased to 745.30 Mb (47.5% reduction)
    Mem. usage decreased to  5.72 Mb (57.5% reduction)
    Mem. usage decreased to  0.24 Mb (57.1% reduction)
    Mem. usage decreased to 38.35 Mb (65.3% reduction)
    
    def go_split(s, symbol='-: '):
        # 拼接正则表达式
        symbol = "[" + symbol + "]+"
        # 一次性分割字符串
        result = re.split(symbol, s)
        # 去除空字符
        return [x for x in result if x]
    def get_hour(start, end):
        d = datetime.datetime(*[int(float(i)) for i in go_split(start)]) - datetime.datetime(*[int(float(i)) for i in go_split(end)])
        n = int(d.days*24 + d.seconds/60/60)
        return n
    def get_first_hour_gap(x):
        return get_hour(end_day, min(x))
    def get_last_hour_gap(x):
        return get_hour(end_day, max(x))
    def get_act_days(x):
        return len(set([i[:10] for i in x]))
    

    构造训练集-特征1天-用户品类店铺候选集7天-label7天(预测7天)

    • ‘2018-03-29’-‘2018-04-04’
    def get_train_set(end_day):
        
        # 合并数据
        jdata_data = jdata_action.merge(jdata_product, on=['sku_id'])
        
        # 候选集 7天
        # '2018-03-29'-'2018-04-04'
        train_set = jdata_data[(jdata_data['action_time'] >= '2018-03-29 00:00:00')
                               & (jdata_data['action_time'] <= '2018-04-04 23:59:59')][
            ['user_id', 'cate', 'shop_id']].drop_duplicates()
        
        # label 7天
        # '2018-04-05'-'2018-04-11'
        train_buy = jdata_data[(jdata_data['action_time'] >= '2018-04-05 00:00:00')
                               & (jdata_data['action_time'] <= '2018-04-11 23:59:59')
                               & (jdata_data['type'] == 2)][['user_id', 'cate', 'shop_id']].drop_duplicates()
        train_buy['label'] = 1
        train_set = train_set.merge(train_buy, on=['user_id', 'cate', 'shop_id'], how='left').fillna(0)
        print('标签准备完毕!')
        
    
        # 提取特征 2018-04-04 1天
        start_day = '2018-04-04 00:00:00'
        for gb_c in [['user_id'],  # 用户
                     ['cate'],  # 品类
                     ['shop_id'],  # 店铺
                     ['user_id', 'cate'],  # 用户-品类
                     ['user_id', 'shop_id'],  # 用户-店铺
                     ['cate', 'shop_id'],  # 品类-店铺
                     ['user_id', 'cate', 'shop_id']]:  # 用户-品类-店铺
            print(gb_c)
            
            action_temp = jdata_data[(jdata_data['action_time'] >= start_day)
                                     & (jdata_data['action_time'] <= end_day)]
    
            # 特征函数
            features_dict = {
                'sku_id': [np.size, lambda x: len(set(x))],
                'type': lambda x: len(set(x)),
                'brand': lambda x: len(set(x)),
                'shop_id': lambda x: len(set(x)),
                'cate': lambda x: len(set(x)),
                'action_time': [
                    get_first_hour_gap,  # first_hour_gap
                    get_last_hour_gap,  # last_hour_gap
                    get_act_days  # act_days
                ]
    
            } 
            features_columns = [c +'_' + '_'.join(gb_c)
                                for c in ['sku_cnt', 'sku_nq', 'type_nq', 'brand_nq', 'shop_nq', 'cate_nq', 'first_hour_gap', 'last_hour_gap', 'act_days']]
            f_temp = action_temp.groupby(gb_c).agg(features_dict).reset_index()
            # print(f_temp.columns)
            f_temp.columns = gb_c + features_columns
            # print(f_temp.columns)
            train_set = train_set.merge(f_temp, on=gb_c, how='left')
    
            for type_ in [1, 2, 3, 4, 5]:  # 1:浏览 2:下单 3:关注 4:评论 5:加购物车
                action_temp = jdata_data[(jdata_data['action_time'] >= start_day)
                                         & (jdata_data['action_time'] <= end_day)
                                         & (jdata_data['type'] == type_)]
                features_dict = {
                    'sku_id': [np.size, lambda x: len(set(x))],
                    'type': lambda x: len(set(x)),
                    'brand': lambda x: len(set(x)),
                    'shop_id': lambda x: len(set(x)),
                    'cate': lambda x: len(set(x)),
                    'action_time': [
                        get_first_hour_gap,  # first_hour_gap
                        get_last_hour_gap,  # last_hour_gap
                        get_act_days  # act_days
                    ]
                }
                features_columns = [c +'_' + '_'.join(gb_c) + '_type_' + str(type_)
                                    for c in ['sku_cnt', 'sku_nq', 'type_nq', 'brand_nq', 'shop_nq', 'cate_nq', 'first_hour_gap', 'last_hour_gap', 'act_days']]
                f_temp = action_temp.groupby(gb_c).agg(features_dict).reset_index()
                if len(f_temp) == 0:
                    continue
                f_temp.columns = gb_c + features_columns
                train_set = train_set.merge(f_temp, on=gb_c, how='left')
            # 浏览、关注、评论购买比,加购物车特征很重要,视B榜数据而定
            train_set['buybro_ratio_' + '_'.join(gb_c)] = train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(1)]
            train_set['buyfocus_ratio_' + '_'.join(gb_c)] = train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(3)]
            train_set['buycom_ratio_' + '_'.join(gb_c)] = train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(4)]
            # train_set['buycart_ratio_' + '_'.join(gb_c)] = train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/train_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(5)]
    
        # 用户特征
        uid_info_col = ['user_id', 'age', 'sex', 'user_lv_cd', 'city_level', 'province', 'city', 'county']
        train_set = train_set.merge(jdata_user[uid_info_col], on=['user_id'], how='left')
        print('用户特征准备完毕!')
    
        # 店铺特征
        shop_info_col = ['shop_id', 'fans_num', 'vip_num', 'shop_score']
        train_set = train_set.merge(jdata_shop[shop_info_col], on=['shop_id'], how='left')
        print('店铺特征准备完毕!')
    
        return train_set
    
    end_day = '2018-04-04 23:59:59'
    train_set = get_train_set(end_day)
    train_set.to_hdf('datasets/train_set.h5', key='train_set', mode='w')
    print(train_set.shape)  # (1560852, 350)
    # print(list(train_set.columns))
    del train_set
    
    标签准备完毕!
    ['user_id']
    ['cate']
    ['shop_id']
    ['user_id', 'cate']
    ['user_id', 'shop_id']
    ['cate', 'shop_id']
    ['user_id', 'cate', 'shop_id']
    用户特征准备完毕!
    店铺特征准备完毕!
    (1560852, 350)
    
    from collections import Counter
    train_set = pd.read_hdf('datasets/train_set.h5', key='train_set')
    y_train = train_set['label'].values
    c = Counter(y_train)
    del train_set, y_train
    print(c) 
    
    Counter({0.0: 1546311, 1.0: 14541})
    

    构造测试集-特征1天-用户品类店铺候选集7天-label7天(预测7天)

    • ‘2018-04-02’-‘2018-04-08’
    • 因为0327-28两天浏览数据严重缺失,训练集从0329开始到0404,与测试集重了三天,理论上训练集与测试集应完全不相关
    def get_test_set(end_day):
        
        # 合并数据
        jdata_data = jdata_action.merge(jdata_product, on=['sku_id'])
        
        # 候选集 7天
        # '2018-04-02'-'2018-04-08'
        test_set = jdata_data[(jdata_data['action_time'] >= '2018-04-02 00:00:00')
                               & (jdata_data['action_time'] <= '2018-04-08 23:59:59')][
            ['user_id', 'cate', 'shop_id']].drop_duplicates()
        
        # label 7天
        # '2018-04-09'-'2018-04-15'
        test_buy = jdata_data[(jdata_data['action_time'] >= '2018-04-09 00:00:00')
                               & (jdata_data['action_time'] <= '2018-04-15 23:59:59')
                               & (jdata_data['type'] == 2)][['user_id', 'cate', 'shop_id']].drop_duplicates()
        test_buy['label'] = 1
        test_set = test_set.merge(test_buy, on=['user_id', 'cate', 'shop_id'], how='left').fillna(0)
        print('标签准备完毕!')
        
        # 提取特征 2018-04-08 1天
        start_day = '2018-04-08 00:00:00'
        for gb_c in [['user_id'],  # 用户
                     ['cate'],  # 品类
                     ['shop_id'],  # 店铺
                     ['user_id', 'cate'],  # 用户-品类
                     ['user_id', 'shop_id'],  # 用户-店铺
                     ['cate', 'shop_id'],  # 品类-店铺
                     ['user_id', 'cate', 'shop_id']]:  # 用户-品类-店铺
            print(gb_c)
            
            action_temp = jdata_data[(jdata_data['action_time'] >= start_day)
                                     & (jdata_data['action_time'] <= end_day)]
    
            # 特征函数
            features_dict = {
                'sku_id': [np.size, lambda x: len(set(x))],
                'type': lambda x: len(set(x)),
                'brand': lambda x: len(set(x)),
                'shop_id': lambda x: len(set(x)),
                'cate': lambda x: len(set(x)),
                'action_time': [
                    get_first_hour_gap,  # first_hour_gap
                    get_last_hour_gap,  # last_hour_gap
                    get_act_days  # act_days
                ]
    
            } 
            features_columns = [c +'_' + '_'.join(gb_c)
                                for c in ['sku_cnt', 'sku_nq', 'type_nq', 'brand_nq', 'shop_nq', 'cate_nq', 'first_hour_gap', 'last_hour_gap', 'act_days']]
            f_temp = action_temp.groupby(gb_c).agg(features_dict).reset_index()
            # print(f_temp.columns)
            f_temp.columns = gb_c + features_columns
            # print(f_temp.columns)
            test_set = test_set.merge(f_temp, on=gb_c, how='left')
    
            for type_ in [1, 2, 3, 4, 5]:  # 1:浏览 2:下单 3:关注 4:评论 5:加购物车
                action_temp = jdata_data[(jdata_data['action_time'] >= start_day)
                                         & (jdata_data['action_time'] <= end_day)
                                         & (jdata_data['type'] == type_)]
                features_dict = {
                    'sku_id': [np.size, lambda x: len(set(x))],
                    'type': lambda x: len(set(x)),
                    'brand': lambda x: len(set(x)),
                    'shop_id': lambda x: len(set(x)),
                    'cate': lambda x: len(set(x)),
                    'action_time': [
                        get_first_hour_gap,  # first_hour_gap
                        get_last_hour_gap,  # last_hour_gap
                        get_act_days  # act_days
                    ]
                }
                features_columns = [c +'_' + '_'.join(gb_c) + '_type_' + str(type_)
                                    for c in ['sku_cnt', 'sku_nq', 'type_nq', 'brand_nq', 'shop_nq', 'cate_nq', 'first_hour_gap', 'last_hour_gap', 'act_days']]
                f_temp = action_temp.groupby(gb_c).agg(features_dict).reset_index()
                if len(f_temp) == 0:
                    continue
                f_temp.columns = gb_c + features_columns
                test_set = test_set.merge(f_temp, on=gb_c, how='left')
            # 浏览、关注、评论购买比,加购物车特征很重要,视B榜数据而定
            test_set['buybro_ratio_' + '_'.join(gb_c)] = test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(1)]
            test_set['buyfocus_ratio_' + '_'.join(gb_c)] = test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(3)]
            test_set['buycom_ratio_' + '_'.join(gb_c)] = test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(4)]
            # test_set['buycart_ratio_' + '_'.join(gb_c)] = test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/test_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(5)]
    
        # 用户特征
        uid_info_col = ['user_id', 'age', 'sex', 'user_lv_cd', 'city_level', 'province', 'city', 'county']
        test_set = test_set.merge(jdata_user[uid_info_col], on=['user_id'], how='left')
        print('用户特征准备完毕!')
    
        # 店铺特征
        shop_info_col = ['shop_id', 'fans_num', 'vip_num', 'shop_score']
        test_set = test_set.merge(jdata_shop[shop_info_col], on=['shop_id'], how='left')
        print('店铺特征准备完毕!')
    
        return test_set
    
    end_day = '2018-04-08 23:59:59'
    test_set = get_test_set(end_day)
    test_set.to_hdf('datasets/test_set.h5', key='test_set', mode='w')
    print(test_set.shape)  # (1560848, 350)
    del test_set
    
    标签准备完毕!
    ['user_id']
    ['cate']
    ['shop_id']
    ['user_id', 'cate']
    ['user_id', 'shop_id']
    ['cate', 'shop_id']
    ['user_id', 'cate', 'shop_id']
    用户特征准备完毕!
    店铺特征准备完毕!
    (1560848, 350)
    
    from collections import Counter
    test_set = pd.read_hdf('datasets/test_set.h5', key='test_set')
    y_train = test_set['label'].values
    c = Counter(y_train)
    del test_set, y_train
    print(c) 
    
    Counter({0.0: 1545471, 1.0: 15377})
    

    构造预测集-特征1天-用户品类店铺候选集7天

    • ‘2018-04-09’-‘2018-04-15’
    def get_pre_set(end_day):
        
        # 合并数据
        jdata_data = jdata_action.merge(jdata_product, on=['sku_id'])
        
        # 预测集 7天
        # '2018-04-09'-'2018-04-15' 
        pre_set = jdata_data[(jdata_data['action_time'] >= '2018-04-09 00:00:00')
                               & (jdata_data['action_time'] <= '2018-04-15 23:59:59')][
            ['user_id', 'cate', 'shop_id']].drop_duplicates()
        
        # 提取特征 2018-04-15 1天
        start_day = '2018-04-15 00:00:00'
        for gb_c in [['user_id'],  # 用户
                     ['cate'],  # 品类
                     ['shop_id'],  # 店铺
                     ['user_id', 'cate'],  # 用户-品类
                     ['user_id', 'shop_id'],  # 用户-店铺
                     ['cate', 'shop_id'],  # 品类-店铺
                     ['user_id', 'cate', 'shop_id']]:  # 用户-品类-店铺
            print(gb_c)
            
            action_temp = jdata_data[(jdata_data['action_time'] >= start_day)
                                     & (jdata_data['action_time'] <= end_day)]
    
            # 特征函数
            features_dict = {
                'sku_id': [np.size, lambda x: len(set(x))],
                'type': lambda x: len(set(x)),
                'brand': lambda x: len(set(x)),
                'shop_id': lambda x: len(set(x)),
                'cate': lambda x: len(set(x)),
                'action_time': [
                    get_first_hour_gap,  # first_hour_gap
                    get_last_hour_gap,  # last_hour_gap
                    get_act_days  # act_days
                ]
    
            } 
            features_columns = [c +'_' + '_'.join(gb_c)
                                for c in ['sku_cnt', 'sku_nq', 'type_nq', 'brand_nq', 'shop_nq', 'cate_nq', 'first_hour_gap', 'last_hour_gap', 'act_days']]
            f_temp = action_temp.groupby(gb_c).agg(features_dict).reset_index()
            # print(f_temp.columns)
            f_temp.columns = gb_c + features_columns
            # print(f_temp.columns)
            pre_set = pre_set.merge(f_temp, on=gb_c, how='left')
    
            for type_ in [1, 2, 3, 4, 5]:  # 1:浏览 2:下单 3:关注 4:评论 5:加购物车
                action_temp = jdata_data[(jdata_data['action_time'] >= start_day)
                                         & (jdata_data['action_time'] <= end_day)
                                         & (jdata_data['type'] == type_)]
                features_dict = {
                    'sku_id': [np.size, lambda x: len(set(x))],
                    'type': lambda x: len(set(x)),
                    'brand': lambda x: len(set(x)),
                    'shop_id': lambda x: len(set(x)),
                    'cate': lambda x: len(set(x)),
                    'action_time': [
                        get_first_hour_gap,  # first_hour_gap
                        get_last_hour_gap,  # last_hour_gap
                        get_act_days  # act_days
                    ]
                }
                features_columns = [c +'_' + '_'.join(gb_c) + '_type_' + str(type_)
                                    for c in ['sku_cnt', 'sku_nq', 'type_nq', 'brand_nq', 'shop_nq', 'cate_nq', 'first_hour_gap', 'last_hour_gap', 'act_days']]
                f_temp = action_temp.groupby(gb_c).agg(features_dict).reset_index()
                if len(f_temp) == 0:
                    continue
                f_temp.columns = gb_c + features_columns
                pre_set = pre_set.merge(f_temp, on=gb_c, how='left')
            # 浏览、关注、评论购买比,加购物车特征很重要,视B榜数据而定
            pre_set['buybro_ratio_' + '_'.join(gb_c)] = pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(1)]
            pre_set['buyfocus_ratio_' + '_'.join(gb_c)] = pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(3)]
            pre_set['buycom_ratio_' + '_'.join(gb_c)] = pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(4)]
            # pre_set['buycart_ratio_' + '_'.join(gb_c)] = pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(2)]/pre_set['sku_cnt_' + '_'.join(gb_c) + '_type_' + str(5)]
    
        # 用户特征
        uid_info_col = ['user_id', 'age', 'sex', 'user_lv_cd', 'city_level', 'province', 'city', 'county']
        pre_set = pre_set.merge(jdata_user[uid_info_col], on=['user_id'], how='left')
        print('用户特征准备完毕!')
    
        # 店铺特征
        shop_info_col = ['shop_id', 'fans_num', 'vip_num', 'shop_score']
        pre_set = pre_set.merge(jdata_shop[shop_info_col], on=['shop_id'], how='left')
        print('店铺特征准备完毕!')
    
        return pre_set
    
    end_day = '2018-04-15 23:59:59'
    pre_set = get_pre_set(end_day)
    pre_set.to_hdf('datasets/pre_set.h5', key='pre_set', mode='w')
    print(pre_set.shape)  
    print(list(pre_set.columns))
    del pre_set
    
    ['user_id']
    ['cate']
    ['shop_id']
    ['user_id', 'cate']
    ['user_id', 'shop_id']
    ['cate', 'shop_id']
    ['user_id', 'cate', 'shop_id']
    用户特征准备完毕!
    店铺特征准备完毕!
    (1569270, 349)
    ['user_id', 'cate', 'shop_id', 'sku_cnt_user_id', 'sku_nq_user_id', 'type_nq_user_id', 'brand_nq_user_id', 'shop_nq_user_id', 'cate_nq_user_id', 'first_hour_gap_user_id', 'last_hour_gap_user_id', 'act_days_user_id', 'sku_cnt_user_id_type_1', 'sku_nq_user_id_type_1', 'type_nq_user_id_type_1', 'brand_nq_user_id_type_1', 'shop_nq_user_id_type_1', 'cate_nq_user_id_type_1', 'first_hour_gap_user_id_type_1', 'last_hour_gap_user_id_type_1', 'act_days_user_id_type_1', 'sku_cnt_user_id_type_2', 'sku_nq_user_id_type_2', 'type_nq_user_id_type_2', 'brand_nq_user_id_type_2', 'shop_nq_user_id_type_2', 'cate_nq_user_id_type_2', 'first_hour_gap_user_id_type_2', 'last_hour_gap_user_id_type_2', 'act_days_user_id_type_2', 'sku_cnt_user_id_type_3', 'sku_nq_user_id_type_3', 'type_nq_user_id_type_3', 'brand_nq_user_id_type_3', 'shop_nq_user_id_type_3', 'cate_nq_user_id_type_3', 'first_hour_gap_user_id_type_3', 'last_hour_gap_user_id_type_3', 'act_days_user_id_type_3', 'sku_cnt_user_id_type_4', 'sku_nq_user_id_type_4', 'type_nq_user_id_type_4', 'brand_nq_user_id_type_4', 'shop_nq_user_id_type_4', 'cate_nq_user_id_type_4', 'first_hour_gap_user_id_type_4', 'last_hour_gap_user_id_type_4', 'act_days_user_id_type_4', 'buybro_ratio_user_id', 'buyfocus_ratio_user_id', 'buycom_ratio_user_id', 'sku_cnt_cate', 'sku_nq_cate', 'type_nq_cate', 'brand_nq_cate', 'shop_nq_cate', 'cate_nq_cate', 'first_hour_gap_cate', 'last_hour_gap_cate', 'act_days_cate', 'sku_cnt_cate_type_1', 'sku_nq_cate_type_1', 'type_nq_cate_type_1', 'brand_nq_cate_type_1', 'shop_nq_cate_type_1', 'cate_nq_cate_type_1', 'first_hour_gap_cate_type_1', 'last_hour_gap_cate_type_1', 'act_days_cate_type_1', 'sku_cnt_cate_type_2', 'sku_nq_cate_type_2', 'type_nq_cate_type_2', 'brand_nq_cate_type_2', 'shop_nq_cate_type_2', 'cate_nq_cate_type_2', 'first_hour_gap_cate_type_2', 'last_hour_gap_cate_type_2', 'act_days_cate_type_2', 'sku_cnt_cate_type_3', 'sku_nq_cate_type_3', 'type_nq_cate_type_3', 'brand_nq_cate_type_3', 'shop_nq_cate_type_3', 'cate_nq_cate_type_3', 'first_hour_gap_cate_type_3', 'last_hour_gap_cate_type_3', 'act_days_cate_type_3', 'sku_cnt_cate_type_4', 'sku_nq_cate_type_4', 'type_nq_cate_type_4', 'brand_nq_cate_type_4', 'shop_nq_cate_type_4', 'cate_nq_cate_type_4', 'first_hour_gap_cate_type_4', 'last_hour_gap_cate_type_4', 'act_days_cate_type_4', 'buybro_ratio_cate', 'buyfocus_ratio_cate', 'buycom_ratio_cate', 'sku_cnt_shop_id', 'sku_nq_shop_id', 'type_nq_shop_id', 'brand_nq_shop_id', 'shop_nq_shop_id', 'cate_nq_shop_id', 'first_hour_gap_shop_id', 'last_hour_gap_shop_id', 'act_days_shop_id', 'sku_cnt_shop_id_type_1', 'sku_nq_shop_id_type_1', 'type_nq_shop_id_type_1', 'brand_nq_shop_id_type_1', 'shop_nq_shop_id_type_1', 'cate_nq_shop_id_type_1', 'first_hour_gap_shop_id_type_1', 'last_hour_gap_shop_id_type_1', 'act_days_shop_id_type_1', 'sku_cnt_shop_id_type_2', 'sku_nq_shop_id_type_2', 'type_nq_shop_id_type_2', 'brand_nq_shop_id_type_2', 'shop_nq_shop_id_type_2', 'cate_nq_shop_id_type_2', 'first_hour_gap_shop_id_type_2', 'last_hour_gap_shop_id_type_2', 'act_days_shop_id_type_2', 'sku_cnt_shop_id_type_3', 'sku_nq_shop_id_type_3', 'type_nq_shop_id_type_3', 'brand_nq_shop_id_type_3', 'shop_nq_shop_id_type_3', 'cate_nq_shop_id_type_3', 'first_hour_gap_shop_id_type_3', 'last_hour_gap_shop_id_type_3', 'act_days_shop_id_type_3', 'sku_cnt_shop_id_type_4', 'sku_nq_shop_id_type_4', 'type_nq_shop_id_type_4', 'brand_nq_shop_id_type_4', 'shop_nq_shop_id_type_4', 'cate_nq_shop_id_type_4', 'first_hour_gap_shop_id_type_4', 'last_hour_gap_shop_id_type_4', 'act_days_shop_id_type_4', 'buybro_ratio_shop_id', 'buyfocus_ratio_shop_id', 'buycom_ratio_shop_id', 'sku_cnt_user_id_cate', 'sku_nq_user_id_cate', 'type_nq_user_id_cate', 'brand_nq_user_id_cate', 'shop_nq_user_id_cate', 'cate_nq_user_id_cate', 'first_hour_gap_user_id_cate', 'last_hour_gap_user_id_cate', 'act_days_user_id_cate', 'sku_cnt_user_id_cate_type_1', 'sku_nq_user_id_cate_type_1', 'type_nq_user_id_cate_type_1', 'brand_nq_user_id_cate_type_1', 'shop_nq_user_id_cate_type_1', 'cate_nq_user_id_cate_type_1', 'first_hour_gap_user_id_cate_type_1', 'last_hour_gap_user_id_cate_type_1', 'act_days_user_id_cate_type_1', 'sku_cnt_user_id_cate_type_2', 'sku_nq_user_id_cate_type_2', 'type_nq_user_id_cate_type_2', 'brand_nq_user_id_cate_type_2', 'shop_nq_user_id_cate_type_2', 'cate_nq_user_id_cate_type_2', 'first_hour_gap_user_id_cate_type_2', 'last_hour_gap_user_id_cate_type_2', 'act_days_user_id_cate_type_2', 'sku_cnt_user_id_cate_type_3', 'sku_nq_user_id_cate_type_3', 'type_nq_user_id_cate_type_3', 'brand_nq_user_id_cate_type_3', 'shop_nq_user_id_cate_type_3', 'cate_nq_user_id_cate_type_3', 'first_hour_gap_user_id_cate_type_3', 'last_hour_gap_user_id_cate_type_3', 'act_days_user_id_cate_type_3', 'sku_cnt_user_id_cate_type_4', 'sku_nq_user_id_cate_type_4', 'type_nq_user_id_cate_type_4', 'brand_nq_user_id_cate_type_4', 'shop_nq_user_id_cate_type_4', 'cate_nq_user_id_cate_type_4', 'first_hour_gap_user_id_cate_type_4', 'last_hour_gap_user_id_cate_type_4', 'act_days_user_id_cate_type_4', 'buybro_ratio_user_id_cate', 'buyfocus_ratio_user_id_cate', 'buycom_ratio_user_id_cate', 'sku_cnt_user_id_shop_id', 'sku_nq_user_id_shop_id', 'type_nq_user_id_shop_id', 'brand_nq_user_id_shop_id', 'shop_nq_user_id_shop_id', 'cate_nq_user_id_shop_id', 'first_hour_gap_user_id_shop_id', 'last_hour_gap_user_id_shop_id', 'act_days_user_id_shop_id', 'sku_cnt_user_id_shop_id_type_1', 'sku_nq_user_id_shop_id_type_1', 'type_nq_user_id_shop_id_type_1', 'brand_nq_user_id_shop_id_type_1', 'shop_nq_user_id_shop_id_type_1', 'cate_nq_user_id_shop_id_type_1', 'first_hour_gap_user_id_shop_id_type_1', 'last_hour_gap_user_id_shop_id_type_1', 'act_days_user_id_shop_id_type_1', 'sku_cnt_user_id_shop_id_type_2', 'sku_nq_user_id_shop_id_type_2', 'type_nq_user_id_shop_id_type_2', 'brand_nq_user_id_shop_id_type_2', 'shop_nq_user_id_shop_id_type_2', 'cate_nq_user_id_shop_id_type_2', 'first_hour_gap_user_id_shop_id_type_2', 'last_hour_gap_user_id_shop_id_type_2', 'act_days_user_id_shop_id_type_2', 'sku_cnt_user_id_shop_id_type_3', 'sku_nq_user_id_shop_id_type_3', 'type_nq_user_id_shop_id_type_3', 'brand_nq_user_id_shop_id_type_3', 'shop_nq_user_id_shop_id_type_3', 'cate_nq_user_id_shop_id_type_3', 'first_hour_gap_user_id_shop_id_type_3', 'last_hour_gap_user_id_shop_id_type_3', 'act_days_user_id_shop_id_type_3', 'sku_cnt_user_id_shop_id_type_4', 'sku_nq_user_id_shop_id_type_4', 'type_nq_user_id_shop_id_type_4', 'brand_nq_user_id_shop_id_type_4', 'shop_nq_user_id_shop_id_type_4', 'cate_nq_user_id_shop_id_type_4', 'first_hour_gap_user_id_shop_id_type_4', 'last_hour_gap_user_id_shop_id_type_4', 'act_days_user_id_shop_id_type_4', 'buybro_ratio_user_id_shop_id', 'buyfocus_ratio_user_id_shop_id', 'buycom_ratio_user_id_shop_id', 'sku_cnt_cate_shop_id', 'sku_nq_cate_shop_id', 'type_nq_cate_shop_id', 'brand_nq_cate_shop_id', 'shop_nq_cate_shop_id', 'cate_nq_cate_shop_id', 'first_hour_gap_cate_shop_id', 'last_hour_gap_cate_shop_id', 'act_days_cate_shop_id', 'sku_cnt_cate_shop_id_type_1', 'sku_nq_cate_shop_id_type_1', 'type_nq_cate_shop_id_type_1', 'brand_nq_cate_shop_id_type_1', 'shop_nq_cate_shop_id_type_1', 'cate_nq_cate_shop_id_type_1', 'first_hour_gap_cate_shop_id_type_1', 'last_hour_gap_cate_shop_id_type_1', 'act_days_cate_shop_id_type_1', 'sku_cnt_cate_shop_id_type_2', 'sku_nq_cate_shop_id_type_2', 'type_nq_cate_shop_id_type_2', 'brand_nq_cate_shop_id_type_2', 'shop_nq_cate_shop_id_type_2', 'cate_nq_cate_shop_id_type_2', 'first_hour_gap_cate_shop_id_type_2', 'last_hour_gap_cate_shop_id_type_2', 'act_days_cate_shop_id_type_2', 'sku_cnt_cate_shop_id_type_3', 'sku_nq_cate_shop_id_type_3', 'type_nq_cate_shop_id_type_3', 'brand_nq_cate_shop_id_type_3', 'shop_nq_cate_shop_id_type_3', 'cate_nq_cate_shop_id_type_3', 'first_hour_gap_cate_shop_id_type_3', 'last_hour_gap_cate_shop_id_type_3', 'act_days_cate_shop_id_type_3', 'sku_cnt_cate_shop_id_type_4', 'sku_nq_cate_shop_id_type_4', 'type_nq_cate_shop_id_type_4', 'brand_nq_cate_shop_id_type_4', 'shop_nq_cate_shop_id_type_4', 'cate_nq_cate_shop_id_type_4', 'first_hour_gap_cate_shop_id_type_4', 'last_hour_gap_cate_shop_id_type_4', 'act_days_cate_shop_id_type_4', 'buybro_ratio_cate_shop_id', 'buyfocus_ratio_cate_shop_id', 'buycom_ratio_cate_shop_id', 'sku_cnt_user_id_cate_shop_id', 'sku_nq_user_id_cate_shop_id', 'type_nq_user_id_cate_shop_id', 'brand_nq_user_id_cate_shop_id', 'shop_nq_user_id_cate_shop_id', 'cate_nq_user_id_cate_shop_id', 'first_hour_gap_user_id_cate_shop_id', 'last_hour_gap_user_id_cate_shop_id', 'act_days_user_id_cate_shop_id', 'sku_cnt_user_id_cate_shop_id_type_1', 'sku_nq_user_id_cate_shop_id_type_1', 'type_nq_user_id_cate_shop_id_type_1', 'brand_nq_user_id_cate_shop_id_type_1', 'shop_nq_user_id_cate_shop_id_type_1', 'cate_nq_user_id_cate_shop_id_type_1', 'first_hour_gap_user_id_cate_shop_id_type_1', 'last_hour_gap_user_id_cate_shop_id_type_1', 'act_days_user_id_cate_shop_id_type_1', 'sku_cnt_user_id_cate_shop_id_type_2', 'sku_nq_user_id_cate_shop_id_type_2', 'type_nq_user_id_cate_shop_id_type_2', 'brand_nq_user_id_cate_shop_id_type_2', 'shop_nq_user_id_cate_shop_id_type_2', 'cate_nq_user_id_cate_shop_id_type_2', 'first_hour_gap_user_id_cate_shop_id_type_2', 'last_hour_gap_user_id_cate_shop_id_type_2', 'act_days_user_id_cate_shop_id_type_2', 'sku_cnt_user_id_cate_shop_id_type_3', 'sku_nq_user_id_cate_shop_id_type_3', 'type_nq_user_id_cate_shop_id_type_3', 'brand_nq_user_id_cate_shop_id_type_3', 'shop_nq_user_id_cate_shop_id_type_3', 'cate_nq_user_id_cate_shop_id_type_3', 'first_hour_gap_user_id_cate_shop_id_type_3', 'last_hour_gap_user_id_cate_shop_id_type_3', 'act_days_user_id_cate_shop_id_type_3', 'sku_cnt_user_id_cate_shop_id_type_4', 'sku_nq_user_id_cate_shop_id_type_4', 'type_nq_user_id_cate_shop_id_type_4', 'brand_nq_user_id_cate_shop_id_type_4', 'shop_nq_user_id_cate_shop_id_type_4', 'cate_nq_user_id_cate_shop_id_type_4', 'first_hour_gap_user_id_cate_shop_id_type_4', 'last_hour_gap_user_id_cate_shop_id_type_4', 'act_days_user_id_cate_shop_id_type_4', 'buybro_ratio_user_id_cate_shop_id', 'buyfocus_ratio_user_id_cate_shop_id', 'buycom_ratio_user_id_cate_shop_id', 'age', 'sex', 'user_lv_cd', 'city_level', 'province', 'city', 'county', 'fans_num', 'vip_num', 'shop_score']
    

    4.特征选择

    特征选择使用随机森林,下面的代码输出特征重要度排名。

    from model.feat_columns import *
    from sklearn.model_selection import train_test_split
    from sklearn.ensemble import RandomForestClassifier
    import numpy as np
    from sklearn.preprocessing import Imputer
    
    """
    使用随机森林进行特征选择
    """
    train_set = pd.read_hdf('../datasets/test_set.h5', key='test_set')
    # train_set = pd.read_hdf('../../datasets/train_set.h5', key='train_set')
    X = train_set[feat_columns].values
    print(X.shape)  # 7day-1 (1560848, 349) (1560848, 328)  7day-7 (1560852, 349)
    
    y = train_set['label'].values
    
    # 如果用全量数据跑不动
    seed = 3
    test_size = 0.3
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=seed)
    
    clf = RandomForestClassifier(random_state=seed)
    # 缺失值填充
    X_train = Imputer().fit_transform(X_train)
    print('fit...')
    clf.fit(X_train, y_train)
    print('done')
    importance = clf.feature_importances_
    indices = np.argsort(importance)[::-1]
    features = train_set[feat_columns].columns
    l = []
    for i in range(X_train.shape[1]):
        print(("%2d) %-*s %f" % (i + 1, 30, features[indices[i]], importance[indices[i]])))
        l.append(features[indices[i]])
    print(l)
    

    5.模型选择

    首先判断一下你要处理的问题属于哪一类,是分类、聚类还是回归等等。确定好类别后,再通过验证集来查看此类中各个算法的表现,从而选择合适的模型。因为目前比赛常用且效果最好的只有lightgbm和xgboost,所以我此次并没有进行模型选择,就用了这两个算法。大家可以查一下sklearn.model_selection包的相关文档。

    from sklearn.model_selection import train_test_split
    from sklearn.model_selection import KFold,StratifiedKFold
    from sklearn.model_selection import StratifiedShuffleSplit
    from sklearn.model_selection import LeaveOneOut
    from sklearn.model_selection import cross_val_score
    

    6.参数选择

    import xgboost as xgb
    from sklearn.model_selection import GridSearchCV
    from collections import Counter
    from model.feat_columns import *
    
    
    train_set = pd.read_hdf('../../datasets/train_set.h5', key='train_set')
    
    X_train = train_set[feat_columns].values
    y_train = train_set['label'].values
    c = Counter(y_train)
    # n = c[0] / 16 / c[1]  # 8
    n = c[0] / c[1]  # 129.56
    
    print(n)
    
    parameters = {
        'max_depth': [5, 10, 15, 20, 25],
        'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],
        'n_estimators': [500, 1000, 2000, 3000, 5000],
        'min_child_weight': [0, 2, 5, 10, 20],
        'max_delta_step': [0, 0.2, 0.6, 1, 2],
        'subsample': [0.6, 0.7, 0.8, 0.85, 0.95],
        'colsample_bytree': [0.5, 0.6, 0.7, 0.8, 0.9],
        'reg_alpha': [0, 0.25, 0.5, 0.75, 1],
        'reg_lambda': [0.2, 0.4, 0.6, 0.8, 1],
        'scale_pos_weight': [0.2, 0.4, 0.6, 0.8, 1, 8, n]
    
    }
    
    xlf = xgb.XGBClassifier(max_depth=10,
                            learning_rate=0.01,
                            n_estimators=2000,
                            silent=True,
                            objective='binary:logistic',
                            nthread=12,
                            gamma=0,
                            min_child_weight=1,
                            max_delta_step=0,
                            subsample=0.85,
                            colsample_bytree=0.7,
                            colsample_bylevel=1,
                            reg_alpha=0,
                            reg_lambda=1,
                            scale_pos_weight=1,
                            seed=1440,
                            missing=None)
    
    gsearch = GridSearchCV(xlf, param_grid=parameters, scoring='accuracy', cv=3)
    gsearch.fit(X_train, y_train)
    
    print("Best score: %0.3f" % gsearch.best_score_)
    print("Best parameters set:")
    best_parameters = gsearch.best_estimator_.get_params()
    for param_name in sorted(parameters.keys()):
        print("\t%s: %r" % (param_name, best_parameters[param_name]))
    

    7.模型训练与评估

    选好特征、模型和参数后开始对模型进行训练和评估,最后再使用前面的测试集(不是这里训练集划分的测试集)查看模型效果。

    import pickle
    from collections import Counter
    from sklearn.metrics import accuracy_score
    from sklearn.model_selection import train_test_split
    from xgboost import XGBClassifier
    from model.feat_columns import *
    
    threshold = 0.3
    
    train_set = pd.read_hdf('../../datasets/train_set.h5', key='train_set')
    
    '''
    pos_sample = train_set[train_set['label'] == 1]
    n = len(pos_sample)
    print(n)
    neg_sample = train_set[train_set['label'] == 0].sample(n=n, random_state=1)
    del train_set
    train_set = pos_sample.append(neg_sample)
    '''
    
    X = train_set[feat_columns].values
    print(X.shape)  # 7day  (1560852, 349)
    
    y = train_set['label'].values
    c = Counter(y)  # Counter({0.0: 1545471, 1.0: 15377})
    print(c)
    
    train_metrics = train_set[['user_id', 'cate', 'shop_id', 'label']]
    del train_set
    
    # split data into train and test sets
    seed = 3
    test_size = 0.33
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=seed)
    
    c = Counter(y_train)
    print(c)  # 7day Counter({0.0: 1035454, 1.0: 10314})
    
    # c[0] / 16 / c[1]  8 | c[0] / c[1]  129.56
    clf = XGBClassifier(max_depth=5, min_child_weight=6, scale_pos_weight=c[0] / 16 / c[1], n_estimators=100, nthread=12,
                        seed=0, subsample=0.5)
    eval_set = [(X_test, y_test)]
    
    clf.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="logloss", eval_set=eval_set, verbose=True)
    # make predictions for test data
    y_pred = clf.predict(X_test)
    predictions = [round(value) for value in y_pred]
    # evaluate predictions
    accuracy = accuracy_score(y_test, predictions)
    print("Accuracy: %.2f%%" % (accuracy * 100.0))
    
    y_train_predict = clf.predict_proba(X)[:, 1]
    # y_train_predict = clf.predict(X)
    # train_metrics['pre_label'] = y_train_predict
    train_metrics['pred_prob'] = y_train_predict
    
    # pred = train_metrics[train_metrics['pre_label'] == 1]
    pred = train_metrics[train_metrics['pred_prob'] > threshold]
    truth = train_metrics[train_metrics['label'] == 1]
    print('X train pred num is:', len(pred))
    
    print("训练集分数:")
    get_final_score(pred, truth)
    del train_metrics
    pickle.dump(clf, open('../user_model/baseline.pkl', 'wb'))
    
    # clf = pickle.load(open('../user_model/baseline.pkl', 'rb'))
    

    8.模型融合

    模型融合就是训练多个模型,然后按照一定的方法整合多个模型输出的结果,常用的有加权平均、投票、学习法等等,请自行百度。模型融合的结果往往优于单个模型,常用于最后的成绩提升。我此次只是对lightgbm和xgboost两个算法预测出的概率进行简单的加权求和,然后取了topN的结果进行提交。


    参考链接:

    • https://mp.weixin.qq.com/s/IWsHchH4Gx0zfDC5rmQmAA
    • https://zhuanlan.zhihu.com/p/64357013
    • https://zhuanlan.zhihu.com/p/47807544
    展开全文
  • 机器学习任务的一般步骤: 那么,在机器学习中,我们的一般步骤是什么呢?当我们拿到数据之后,我们是如何对数据进行分析呢?。这里,我们总结下一般的机器学习任务的步骤,它适用于在上一篇的机器学习简介中,我们...

    机器学习任务的一般步骤:
    那么,在机器学习任务中,将如何对数据进行分析呢?这里,我们总结下一般的机器学习任务的步骤,它适用于在上一篇的机器学习简介中,我们介绍了几种机器学习的类型。

    文章目录


    #1、确定特征#
      在机器学习中,我们拿到的数据集,一般都是结构化的数据,那么在对这些数据的处理时,我们就需要判断这些数据是否有用,那就是需要确定这些数据的特征,这些特征对我们最终预测的结果有多大的影响。如在波士顿房价预测中,我们选择的特征有房子的房间数、房子的面积等都影响房价的预测。机器学习的特征选择是非常重要的,它决定了我们的最终数据的预测判断。这里,我主要简单介绍一下关于特征选择的一些基本知识。下图是特征工程的一些方法:
    这里写图片描述
      后面另起章节对特征工程进行讲解

    #2、确定模型 #
      模型选择,就是在选择何种数学公式对数据进行预测。当我们确定特征后,我们就需要将数据带入到相应的模型进行训练,在监督学习的任务中,在给定的带标签的训练样本D={xi,yi}i=1N\textit{D}=\left \{ \mathbf{x}_{i} ,y_{i}\right \}_{i=1}^{N} 学习到了一个xy^\mathbf{x}\rightarrow\hat{y}的映射关系,从而得到对新的输入x\mathbf{x}进行预测。模型就是指对给定的x\mathbf{x},如何预测其标签 y^\hat{y}
      线性模型(最简单的模型):
      
            f(x)=Σjwixi=WTXf(\mathbf{x})=\Sigma _{j}w_{i}x_{i}=\mathbf{W^{T}}\boldsymbol{X}
            
      非线性模型(在线性模型的非线性化的条件下): 
      
            基函数:x2x^{2}、log、exp、样条函数、决策树……
            核化:将原问题转化为对偶问题,将对偶问题中的向量点积&lt;xi,xj&gt;&lt;\mathbf{x}_{i},\mathbf{x}_{j}&gt;换成核函数k(xi,xj)k(\mathbf{x}_{i},\mathbf{x}_{j})
            
    但是我们的预测目标是使得真值和预测值之间的误差是极小值,所以我的训练函数应该是得到一个目标函数。
    目标函数:损失函数正则项
     这里写图片描述
    损失函数:
    度量模型预测值和真值之间的差异
    对于回归的问题,主要的损失函数有如下:令残差 r=f(x)yr = f(x)-y  
          --L2损失:L2(r)=12r2L_{2}(r) = \frac{1}{2}r^{2}
          --L1损失:L1(r)=rL_{1}(r)=|r|
          --Huber损失:Lδ(r)={12r2 if rδδr12δ2 if r&gt;δL_{\delta }(r)=\begin{cases}\frac{1}{2}r^{2} &amp; \text{ if } |r|\leq \delta \\ \delta |r|-\frac{1}{2}\delta^{2} &amp; \text{ if } |r|&gt; \delta \end{cases}
    对于分类问题,主要的损失函数有如下:
          – 0-1损失:l0/1(y,f(x))={1 if yf(x)&lt;00 if othereisel_{0/1}(y,f(x))=\begin{cases}1 &amp; \text{ if } yf(x)&lt;0 \\ 0 &amp; \text{ if } othereise \end{cases}
          – Logistic 损失:也称为负log似然损失/logloss : llog(y,f(x))=log(1+exp(yf(x)))l_{log}(y,f(x))=log(1+exp(-yf(x)))
          – 指数损失:lexp(y,f(x))=exp(yf(x))l_{exp}(y,f(x))=exp(-yf(x))
          – 合页损失:lhinge(y,f(x))=max(0,1yf(x))l_{hinge}(y,f(x))=max(0,1-yf(x))
    正则项:
      但是就算我们在训练集中能够把训练数据训练得到的损失最小,甚至为零,但是我们真正关心的是在预测上的性能,对于机器学习的模型来说,越是复杂的模型,越是拟合的很好,损失也越小,但是当在训练集上,它的方差就越大。所以要我们对模型进行惩罚,就得加入正则项。常用的正则项有如下:
          - L2正则:R(θ)=λθ22=j=1Dθj2R(\mathbf{\theta})=\lambda||\mathbf{\theta}||^{2}_{2}=\sum_{j=1}^{D}\theta ^{2}_{j}
          - L1正则:R(θ)=λθ=j=1DθR(\mathbf{\theta})=\lambda|\mathbf{\theta}|=\sum_{j=1}^{D}|\theta|
          - L0正则:R(θ)=λθ0R(\mathbf{\theta})=\lambda||\mathbf{\theta}||_{0}
    下面谈论下正则的必要性:
    通过sin曲线进行拟合:
           $Y=sin(2\pi X)+\varepsilon $
           XX服从高斯分布:XUniform[0,1],εN(0,0.32)X\sim Uniform[0,1],\varepsilon \sim N(0,0.3^{2})
     预测模型(M阶多项式):
           y^=j=0Mwjxj\hat{y}=\sum_{j=0}^{M}w_{j}x^{j}(样本是N=10)
           这里我们使用L2损失函数 1Ni=1N(yy^)2\frac{1}{N}\sum_{i=1}^{N}(y-\hat{y})^2
       这里写图片描述
     现在我们需拟合这个函数:
     (1)、0阶多项式拟合:
     y^=w0\hat{y}=w_{0} ,如下图红线就是该函数,拟合情况不是很好,样本点基本都不在红线附近
     这里写图片描述
     (2)、1阶多项式拟合:
     y^=w0+w1x\hat{y}=w_{0}+w_{1}x,拟合情况比0阶好了一点
     这里写图片描述
     (3)、3阶多项式拟合:
     y^=w0+w1x+w2x2\hat{y}=w_{0}+w_{1}x+w_{2}x^{2},拟合情况比刚刚又好了很多,基本所有的点都落在红线上了
     这里写图片描述
     (4)、9阶多项式拟合:
     y^=w0+w1x+w2x2+w3x3....w9x9\hat{y}=w_{0}+w_{1}x+w_{2}x^{2}+w_{3}x^{3}....w_{9}x^{9}。可以看到所有的点都落在红线
     这里写图片描述
     但是,如果新增数据集的话,如下图,A点和B点就不落在红线上。而我们说当预测值和真值之间差异(方差)最小时,该模型才是最佳模型,但是目前看来,该模型在训练集上拟合的很好,误差为0,但是校验集上误差就很大。
     这里写图片描述
    上述的现象看出,当模型复杂度增加时,训练误差继续下降,甚至趋向于0,但是测试误差却反而增大了,这种现象我们称之为过拟合(overfitting)。一般的模型都遵从这种规律,当模型复杂度到达某个值后,随着模型越来越复杂,预测值和真值之间的误差就越大:
    这里写图片描述
    考虑到这种情况,我们就需要增加一个正则项,对模型复杂度进行惩罚,避免出现过拟合的情况,如下图:
    这里写图片描述
    这里我们是增加了L2正则(当然还可以是其他正则),目标函数(使用L2损失和L2正则,称之为岭回归)如下:
    这里写图片描述
    有过拟合就有欠拟合,欠拟合是指模型太简单或者对复杂性惩罚太多
    常见的线性模型的损失函数和正则项的组合:
    这里写图片描述
    #3、模型训练#
    模型训练也就是我们的目标函数的优化,也就是对目标函数进行求解。简单的函数直接通过导数求解,对于比较复杂的函数,有凸优化等方式,如随机梯度下降法和牛顿法等
    梯度下降法的简单介绍:快速找到局部极小值。将函数比作一座小山,我们站在某个山坡上,望四周看,从哪个 方向往下走,能最快走到底部,就是梯度的方向
        a.给定初始值 θ0\theta^{0}
        b.更新θ\theta,使得J(θ)J(\theta)越来越小:
           θt=θt1ηθJ(θ)\mathbf{\theta }^{t} = \mathbf{\theta }^{t1}-\eta \triangledown _{\theta}J(\theta)
        直到收敛到或者达到预先设定的最大迭代数
    不过,梯度下降有如下几点需要注意:
    (1)、在使用梯度下降的时候,我们需要注意到,如果下降的步伐太小(η\eta学习率)的话,收敛就会很慢,如果太大的话,容易出现overshoot the mininum的现象,如下图:

    这里写图片描述
    一直来回震荡,得不到收敛。所以在训练时候,如果发现函数值增加的话,需要适当减小学习率etaeta的值。

    (2)、在我们的梯度下降的时候,我们得到的只是局部最小值,不是整个模型的最小值。如果二阶导数恒大于0,那么目标函数就是凸函数,所以局部最小值就是全局的最小值。如果不是的话,那么我们只能通过随机选择不同的初始值,得到多个局部极小值点。多个局部极小值的最小值就是函数的全局最小值。

    #4、模型选择和评估#
    同一个问题,可以使用不同的模型去预测,但是最终选择哪个模型,就需要看该模型在新的数据集上的预测误差是否是最小的,那么新的数据集就是校验集。如下所示:
    这里写图片描述

    通常来讲,我们也无法确定多少数据是足够的,没有一个标准去确定;同时也没有足够的样本给我们训练和校验。所以我们得通过其他技术来对数据集进行划分规划。如可以通过重采样技术来模拟校验集数据,如重采样的两个方式:
    (1)、交叉验证
    (2)、bootstrap
    这里简单介绍交叉验证:
    K-折交叉验证:
      交叉验证(Cross Validation ,CV),将训练数据分为容量相等的K份,对于每个k = 1,2,3…K 。留出第k份,其他K-1份作为训练数据,第k份为校验数据,作为预测误差的数据集。交叉验证估计的误差为:
            CV(M)=1Kk=1KEk(M)CV(M)=\frac{1}{K}\sum_{k=1}^{K}E_{k}(M)
    对于不同的模型,计算其对于的误差CV(M),最佳模型为CV(M)最小的模型。模型复杂度和泛化误差的关系通常是U型曲线,如下图,当模型复杂度一定是,得到预测值与真值之间的误差最小,那么这个复杂度就是我们需要的模型复杂度:
    这里写图片描述
    那么通过校验集得到预测结果后,还需要使用如下一些评估标准进行度量预测的拟合效果:
    (1)、开平均方误差(rooted mean squared error , RMSE):RMSE=1Ni=1N(yi^yi)2\sqrt{\frac{1}{N}\sum_{i=1}^{N}(\hat{y_{i}}-y_{i})^{2}}
    (2)、平均绝对误差(mean absolute error, MAE):MAE=1Ni=1Nyi^yi\frac{1}{N}\sum_{i=1}^{N}|\hat{y_{i}}-y_{i}|
    (3)、R2 score:即考虑预测值和真值之间的差异,也考虑了问题本身真值之间的差异(scikit learn线性回归的缺省评价准则)
            SSres=i=1N(yi^yi)2SS_{res}=\sum_{i=1}^{N}(\hat{y_{i}}-y_{i})^{2}
            SStot=i=1N(yiyˉ)2SS_{tot}=\sum_{i=1}^{N}(y_{i}-\bar{y})^{2}
            R2=1SSresSStotR^{2}=1-\frac{SS_{res}}{SS_{tot}}
    所以,R2R^{2}越大,模型越好。
    #5、模型预测和应用#
    当选好模型后,就可以使用该模型在现实中进行应用了。也就是可以上线使用

    展开全文
  • 在我们准备用机器学习构建一个分类器来处理实际问题时,还需要做些其他的准备工作: 1. 根据你的问题选择一种合适的机器学习方法,因为每种...机器学习一般步骤可以归纳为两个: 训练 测试 训练 这一步主要是根据数

    在我们准备用机器学习构建一个分类器来处理实际问题时,还需要做些其他的准备工作:

    1. 根据你的问题选择一种合适的机器学习方法,因为每种机器学习的算法都有各自不同的特点,能适应的场景也不同,所以选择合适的机器学习方法事半功倍。
    2. 根据你的问题选择合适的特征来进行分析,因为事物之间都有自己的特征,选择好事物独特的特征来进行也能提高训练效果。
    3. 根据你的问题设置合适的分析模型参数,每一种机器学习算法都会依据模型参数设置决策边界。

    机器学习的一般步骤可以归纳为两个:

    • 训练
    • 测试

    训练

    这一步主要是根据数据确定用于训练的特征向量,然后设置训练的参数,构建分类器模型。

    • 为了得到高精度的预测,选择合适的特征是非常重要的。另外,每一种机器学习方法都有各自的特征数据类型的格式,例如算法模型接受(x,y)作为参数,那么有的x,y可能只能是0、1;有的可能是其他的要求。
    • 每一种机器学习方法都有一套独特的参数集,如逻辑回归,需要调节的通常只有正则项系数C;如随机森林,需要调节的变量会多出不少;再如神经网络中的神经元个数…在训练的过程中,模型的参数会根据测试的结果不断的被修改和调整,直到找到合适的模型。

    测试

    根据测试数据集确定用于测试的特征向量,注意,训练和测试的数据集是不同的,然后根据测试结果,选择最佳的模型。

    • 同训练数据集同样的特征和同样的模型的参数

    在使用机器学习时,训练数据集下的预测效果很好,但是测试集中表现不好的模式有两种:

    • 将认为有意义的数据,其实是无意义的干扰数据混到训练数据集
    • 根据训练数据中的特有数据进行分类,比如西瓜的产量,训练集中的数据是中国西瓜的产量,但是测试数据使用的是外国西瓜的产量,那么结果肯定就不准了。所以如果不把这一点考虑在内,只对中国西瓜产量的训练数据集模型进行调整,那么面对测试训练集也不会有好的效果,在实际中也无法应用

    出现这两种问题的原因是机器学习模型是从训练数据集中学习而来,过度依赖于数据集了,这一问题也别叫作**“过拟合问题”**。

    总结

    实际上,机器学习就是不断的重复训练-》测试…直到找到最佳模型。

    展开全文
  • 1、使用机器学习来解决问题,我们用数学语言来描述它,然后建立一个模型,例如回归模型或者分类模型等来描述这个问题; 2、通过最小化误差、最大似然、最大后验概率等等建立模型的代价函数,转化为最优化问题。找到...

    各位工程师累了吗? 推荐一篇可以让你技术能力达到出神入化的网站["宅男门诊"](https://zhainanmenzhen.com/)

    1、使用机器学习来解决问题,我们用数学语言来描述它,然后建立一个模型,例如回归模型或者分类模型等来描述这个问题;

    2、通过最小化误差、最大似然、最大后验概率等等建立模型的代价函数,转化为最优化问题。找到最优化问题的解,也就是能拟合我们的数据的最好的模型参数;

    3、求解这个代价函数,找到最优解。

    求最优解方法:

    1、如果优化函数存在解析解。例如我们求最值一般是对优化函数求导,找到导数为0的点。如果代价函数能简单求导,并且求导后为0的式子存在解析解,那么我们就可以直接得到最优的参数。

    2、如果式子很难求导,例如函数里面存在隐含的变量或者变量相互间存在耦合,互相依赖的情况。或者求导后式子得不到解释解,或者未知参数的个数大于方程组的个数等。这时候使用迭代算法来一步一步找到最优解。

    特别的若优化函数是凸函数,那么就存在全局最优解,如果函数是非凸的,那么就会有很多局部最优的解,因此凸优化重要性不言而喻。人们总希望在万千事物中找到最优的那个他。

    1.什么是机器学习

    计算机自动从数据中发现规律,并应用于解决新问题

    给定数据(X1,Y1), (X2,Y2), … ,(Xn,Yn),机器自动学习X和Y之间的关系,从而对新的Xi,能够预测Yi。如由身高预测性别,身高预测体重。

    机器学习是一门人工智能的科学,该领域的主要研究对象是人工智能,特别是如何在经验学习中改善具体算法的性能。

    2.基于规则

    image

    3.基于模型- 机器学习

    image

    4.实例-房价预测

    image

    image

     

    5.基本概念

    我们先明确机器学习中一些概念和常用的符号:

    房屋销售记录表 训练集(training set)或者训练数据(training data), 一般称为x

    房屋销售价钱 输出数据,一般称为y

    拟合的函数 (模型、假设),一般写做 y = h(x)

    训练数据的条数(training set) 一条训练数据是由一对输入和输出数据组成的

    输入数据的维度(特征的个数features) 房屋的售价,数据表中的列

    6.机器学习过程

    image

    基本概念:

    image

    7.机器学习主要问题

    分类:LR,SVM,NB,KNN,决策树

     

    LR(logistic regression),SVM(),NB(naive bayes ),KNN(k-nearest neighbor),决策树

    聚类:k均值(k-means),层次,GMM(高斯混合模型)

    回归:线性回归,逻辑回归

    关联规则:Apriori,FPgrowth

    image

     

    8.监督与非监督学习

    监督学习:

    给定数据(X1,Y1),(X2,Y2),…,(Xn,Yn)

    对新的Xi,预测其Yi

    分类,回归

     

    非监督学习:

    给定数据X1,X2,…,Xn

    求Yi=f(Xi),P(Xi,Yi)

    聚类,降维

    9.机器学习三要素

    image

    模型---规律

    image

    策略---模型好不好

    image

    image

    image

    10.经验风险

    image

    image

    11.结构风险

    image

    image

    12.算法

    image

    13.正则化

    正则化(regularization)在线性代数理论中,不适定问题通常是由一组线性代数方程定义的,而且这组方程组通常来源于有着很大的条件数的不适定反问题

    image

    image

     

    14.交叉验证

    image

    1. 简单交叉验证

    简单交叉验证的方法是这样的,随机从最初的样本中选择部分,形成验证数据,而剩下的当作训练数据。一般来说,少于三分之一的数据被选作验证数据。

    2. K折交叉验证

    10折交叉验证是把样本数据分成10份,轮流将其中9份做训练数据,将剩下的1份当测试数据,10次结果的均值作为对算法精度的估计,通常情况下为了提高精度,还需要做多次10折交叉验证。

    更进一步,还有K折交叉验证,10折交叉验证是它的特殊情况。K折交叉验证就是把样本分为K份,其中K-1份用来做训练建立模型,留剩下的一份来验证,交叉验证重复K次,每个子样本验证一次。

    3. 留一验证

    留一验证只使用样本数据中的一项当作验证数据,而剩下的全作为训练数据,一直重复,直到所有的样本都作验证数据一次。可以看出留一验证实际上就是K折交叉验证,只不过这里的K有点特殊,K为样本数据个数。

    15.泛化能力(预测能力)

    泛化能力指由学习方法得到的模型对未知数据的预测能力。

    概括地说,所谓泛化能力(generalization ability)是指机器学习算法对新鲜样本的适应能力。学习的目的是学到隐含在数据对背后的规律,对具有同一规律的学习集以外的数据,经过训练的算法也能给出合适的输出,该能力称为泛化能力。

     

    16.模型评估与模型选择

    当损失函数给定时,基于损失函数的模型的训练误差和模型的测试误差就自然成为学习方法评估的标准。

    image

     

    image

     

    通常,测试误差越小的方法具有更好的预测能力,泛化能力强。

     

    17.过拟合与模型选择

    image

     

    image

     

    image

    18.总结

    image

    转载于:https://www.cnblogs.com/chaoren399/p/4851658.html

    展开全文
  • 一个完整的机器学习项目一般流程包括:1、抽象成数学问题  首先要明确问题,分类还是回归,尽量避免胡乱尝试; 2、数据获取及分析  获取的数据要有代表性,否则必然会过拟合。 而且对于分类问题,数据偏斜不能...
  • 机器学习任务的一般步骤 一、确定特征:(收集训练数据) 1 &amp;gt; 数据探索:(为什么要进行数据探索呢:有助于选择 合适的 数据预处理方法 和 建模方法) (1)数据质量分析 -- 缺失值 -- 异常值 ...
  • 机器学习学习步骤

    2020-03-11 23:49:43
    1 开始第一个项目 a 数据收集整理 比如Imagenet水果识别,10种水果图片,每种几千张 ...根据gpu显存情况、业务需求、数据集大小选择, 部署移动端一般选择轻量高效率,比如ShuffleNet、SqueezeNet、MobileNet等...
  • 一般步骤 一、得到数据集并做预处理 1.分割数据集(train_test_split) 可以用train_test_split来处理得到的数据集,代码基本形式如下: from sklearn.model_selection import train_test_split X_train, X_test, Y_...
  • 机器学习算法步骤

    2018-05-26 22:48:03
    机器学习算法一般是这样一个步骤:1)对于一个问题,我们用数学语言来描述它,然后建立一个模型,例如回归模型或者分类模型等来描述这个问题;2)通过最大似然、最大后验概率或者最小化分类误差等等建立模型的代价...
  • 机器学习算法调优的一般步骤

    万次阅读 2016-11-01 21:48:20
    机器学习分类结果不理想时,下一步应该怎么办?如何check,怎么调整?
  • 机器学习

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 653
精华内容 261
关键字:

机器学习一般步骤