• 天池新人赛-天池新人实战赛o2o优惠券使用预测(一)


      第一次参加天池新人赛,主要目的还是想考察下自己对机器学习上的成果,以及系统化的实现一下所学的东西。看看自己的掌握度如何,能否顺利的完成一个分析工作。为之后的学习奠定基础。

      这次成绩并不好,只是把整个机器学习的流程熟悉了下。我本人总结如下:

      步骤一:读懂题目含义,分析赛题的数据

      步骤二:特征工程的设计,这部分非常重要,好的特征工程能大大提高模型的准确率

      步骤三:训练算法。区分训练集、测试集等。

      步骤四:测试模型,看效果如何。

      赛题可以去天池的官网查看,里面有赛题说明,赛题数据等等

      https://tianchi.aliyun.com/getStart/introduction.htm?spm=5176.11165418.333.1.3c2e613cd1CCDk&raceId=231593

      以下是代码部分:

      

    1 import numpy as np
    2 import pandas as pd
    3 
    4 #导入数据
    5 train_online = pd.read_csv('ccf_online_stage1_train.csv')
    6 train_offline = pd.read_csv('ccf_offline_stage1_train.csv')
    7 test = pd.read_csv('ccf_offline_stage1_test_revised.csv')
    1 #将数据合并,以便统一对数据进行处理。都是线下数据
    2 all_offline = pd.concat([train_offline,test])
    1 #查看每一列的异常值
    2 f = lambda x:sum(x.isnull())
    3 all_offline.apply(f)

      

     1 #Data的空值 赋值为null,统一空值的格式
     2 all_offline['Date'] = all_offline['Date'].fillna('null')
     3 
     4 #将online与offline的数据合并
     5 pd.merge(all_offline,train_online,on=['Merchant_id','User_id'])
     6 
     7 #通过合并数据,发现两者并无交集,题目要求只用线下预测,故排除线上online数据,
     8 #只用offline数据
     9 
    10 #根据赛题的要求,把正负样本标注出来
    11 def is_used(column):
    12     if column['Date']!='null' and column['Coupon_id']!='null':
    13         return 1
    14     elif column['Date']=='null' and column['Coupon_id']!='null':
    15         return -1
    16     else:
    17         return 0
    18 
    19 all_offline['is_used'] = all_offline.apply(is_used,axis=1)
    View Code
    1 #Coupon_id 优惠券ID的具体数值意义不大,因此我们把他转换成:是否有优惠券
    2 def has_coup(x):
    3     if x['Coupon_id'] != 'null':
    4         return 1
    5     else:
    6         return 0
    7     
    8 all_offline['has_coup']=all_offline.apply(has_coup,axis=1)
     1 #由于Discount_rate优惠率的特殊格式:"150:20",很难使用算法来计算使用
     2 #根据实际情况,优惠力度是能够影响优惠券的使用频率的。因此需要对Discount_rate进行转化
     3 #根据Discount_rate标识出折扣率
     4 import re
     5 regex=re.compile('^d+:d+$')
     6 
     7 def discount_percent(y):
     8     if y['Discount_rate'] == 'null' and y['Date_received'] == 'null':
     9         return 'null'
    10     elif re.match(regex,y['Discount_rate']):
    11         num_min,num_max=y['Discount_rate'].split(':')
    12         return float(num_max)/float(num_min)
    13     else:
    14         return y['Discount_rate']
    15 
    16 all_offline['discount_percent'] = all_offline.apply(discount_percent,axis=1)
    View Code
     1 #在进一步想,优惠力度会影响优惠券使用的概率,x:y这种满减的类型,x具体是多少,势必也会影响优惠券使用率
     2 #讲满x元的标出x元
     3 def discount_limit(y):
     4     if y['Discount_rate'] == 'null' and y['Date_received'] == 'null':
     5         return 'null'
     6     elif re.match(regex,y['Discount_rate']):
     7         num_min,num_max=y['Discount_rate'].split(':')
     8         return num_min
     9     else:
    10         return 0
    11 
    12 all_offline['discount_limit'] = all_offline.apply(discount_limit,axis=1)
    13 all_offline.head(10)

      

     1 #由于赛题需要的是,优惠券领取后15天的使用概率
     2 #因此,我们在is_used的基础上,在对领券时间 Date_received 和使用时间Date,进行比较,判断是否在15天内使用
     3 #时间比较
     4 import datetime
     5 #标注15天内使用优惠券的情况
     6 def used_in_15days(z):
     7     if z['is_used'] == 1 and z['Date'] != 'null' and z['Date_received'] != 'null':
     8         days= (datetime.datetime.strptime(z['Date'],"%Y%m%d")-datetime.datetime.strptime(z['Date_received'],"%Y%m%d"))
     9         if days.days < 15:
    10             return 1
    11         else:
    12             return 0
    13     else:
    14         return 0
    15         
    16 all_offline['used_in_15days']=all_offline.apply(used_in_15days,axis=1)
    1 #再来观察discount_percent,discount_limit这2个特征,看数据的分布情况。
    2 all_offline['discount_percent'].value_counts()

       

    1 all_offline['discount_limit'].value_counts()

       

    #将discount_percent分段
    def discount_percent_layer(columns):
        if columns['discount_percent']=='null':
            return 'null'
        
        columns['discount_percent']=float(columns['discount_percent'])
        if columns['discount_percent'] <= 0.1:
            return 0.1
        elif columns['discount_percent'] <= 0.2:
            return 0.2
        elif columns['discount_percent'] <= 0.3:
            return 0.3
        elif columns['discount_percent'] <= 0.4:
            return 0.4
        else:
            return 0.5
    
    all_offline['discount_percent_layer']=all_offline.apply(discount_percent_layer,axis=1)
    all_offline['discount_percent_layer'].value_counts()

     ·  

     1 #将discount_limit分段
     2 def discount_limit_layer(columns):
     3     if columns =='null':
     4         return 'null'
     5     
     6     columns=int(columns)
     7     if columns <= 10:
     8         return 10
     9     elif columns <= 20:
    10         return 20
    11     elif columns <= 30:
    12         return 30
    13     elif columns <= 50:
    14         return 50
    15     elif columns <= 100:
    16         return 100
    17     elif columns <= 200:
    18         return 200
    19     else:
    20         return 300
    21 
    22 all_offline['discount_limit_layer']=all_offline['discount_limit'].apply(discount_limit_layer)
    23 all_offline['discount_limit_layer'].value_counts()

       

    总结:
      此时 Coupon_id 被处理成 has_coup(1代表领取优惠券,0代表没有领取优惠券)
      Date,Date_received 被处理成 used_in_15days。表示是否在15天内使用过优惠券
      Discount_rate 被处理成 discount_percent(折扣率),discount_limit(满多少)
      Merchant_id,User_id 是unicode值,不需要进行处理

    1 #剩下Distance,看下Distance的分布情况
    2 all_offline['Distance'].value_counts()

      

    1 #保存数据,以便后期使用起来方便
    2 train_finall,test_finall = all_offline[:train_offline.shape[0]],all_offline[train_offline.shape[0]:]
    3 all_offline.to_csv(r'outputall_offline.csv')
    4 train_finall.to_csv(r'output	rain_finall.csv')
    5 test_finall.to_csv(r'output	est_finall.csv')
    1 #one_hot处理
    2 all_offline_new=all_offline.drop(
    3         ['Coupon_id','Date','Date_received','Discount_rate','Merchant_id',
    4          'User_id','discount_percent','discount_limit'],axis=1)
    5 all_offline_new=pd.get_dummies(all_offline_new)
     1 #把测试集跟验证集分开
     2 train01,test01=all_offline_new[:len(train_offline)],all_offline_new[len(train_offline):]
     3 
     4 #把没有领券的去掉
     5 train02=train01[train01['has_coup']==1]
     6 
     7 #由于特征集 都是领券的人,故把 has_coup 字段删掉
     8 train02=train02.drop(['has_coup'],axis=1)
     9 test01=test01.drop(['has_coup'],axis=1)
    10 
    11 x_train=train02.drop(['used_in_15days'],axis=1)
    12 y_train=pd.DataFrame({"used_in_15days":train02['used_in_15days']})
    13 x_text=test01.drop(['used_in_15days'],axis=1)
     1 #建模
     2 from sklearn.linear_model import LinearRegression
     3 
     4 clf=LinearRegression()
     5 clf.fit(x_train,y_train)
     6 
     7 #用模型进行预测
     8 predict=clf.predict(x_text)
     9 
    10 
    11 result=pd.read_csv('ccf_offline_stage1_test_revised.csv')
    12 result['probability']=predict
    13 
    14 result=result.drop(['Merchant_id','Discount_rate','Distance'],axis=1)
    15 
    16 
    17 #发现最终预测有负值,直接归为0
    18 result['probability']=result['probability'].apply(lambda x: 0 if x<0 else x)
    19 
    20 result.to_csv(r'output/sample_submission.csv',index=False)
  • 相关阅读:
    Leetcode(337)-打家劫舍III
    Leetcode(213)-打家劫舍II
    Leetcode(198)-打家劫舍
    Leetcode(32)-最长有效括号
    计数排序
    智能指针
    C++中的explicit
    Leetcode(878)-第 N 个神奇数字
    Leetcode(877)-石子游戏
    C++的memset
  • 原文地址:https://www.cnblogs.com/yaowentao/p/8398735.html
Copyright © 2020-2023  润新知