吃鸡攻略

欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。

作者:海笛heidi

个人公众号: 废才数据挖掘

    绝地求生相信大家都比较熟悉,本次推文就是利用kaggle数据预测玩家排名情况,有兴趣的小伙伴可在kaggle下载数据,数据链接

:https://www.kaggle.com/c/pubg-finish-placement-prediction

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib
from sklearn.model_selection import GridSearchCV
import lightgbm as lgb 
from sklearn.cross_validation import train_test_split,cross_val_score
from sklearn.model_selection import StratifiedKFold,KFold,StratifiedShuffleSplit
import lightgbm as lgb
import seaborn as sns
import warnings
import card
import time
import gc, sys
matplotlib.use('qt4agg')#指定默认字体
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['font.family']='sans-serif'#解决负号'-'显示为方块的问题
matplotlib.rcParams['axes.unicode_minus'] = False
pd.set_option('display.max_rows', 100)
pd.set_option('display.max_columns', 10000)
%matplotlib inline
warnings.filterwarnings("ignore")
plt.style.use('ggplot')

  导入数据

def file():
    train=pd.read_csv("d:/data/PUBG/train_V2.csv")
    test=pd.read_csv("d:/data/PUBG/test_V2.csv")
    sub=pd.read_csv("d:/data/PUBG/sample_submission_V2.csv")
    return train ,test ,sub

a=time.time()
train ,test ,sub=file()
b=time.time()
costime=b-a
print(costime)


    我们先看下原始特征名称

oldname=['Id', 'groupId', 'matchId', 'assists', 'boosts', 'damageDealt', 'DBNOs',
       'headshotKills', 'heals', 'killPlace', 'killPoints', 'kills',
       'killStreaks', 'longestKill', 'matchDuration', 'matchType', 'maxPlace',
       'numGroups', 'rankPoints', 'revives', 'rideDistance', 'roadKills',
       'swimDistance', 'teamKills', 'vehicleDestroys', 'walkDistance',
       'weaponsAcquired', 'winPoints', 'winPlacePerc']

    为了方便,小编在这里把变量改为中文名,部分翻译不太准确,敬请谅解。

train.columns=['Id', 'groupId', 'matchId', '助攻数', '使用药品', '总伤害','击倒数',
               '爆头杀敌', '治疗', '杀敌数排名', '杀敌数外部排名', '杀敌数',
               '短时间最大杀敌', '死亡前最大时间', '比赛时间', '比赛类型', 'maxPlace',
               '有数据的组数', 'Elo玩家排名', 'revives', '车辆行驶距离', '路上杀敌数'
               , '游泳距离', '杀队友次数', '摧毁车辆数', '步行距离', 
               '捡拾武器数', '积分', 'target']

    现在我们来做一下简单的EDA

PUBG=train.copy()
PUBG.head()


3901436-0d686db337ebcc3c


    比赛时间为千位数,为了方便大家认知,把时间除以100得到场均存活分钟数


PUBG["比赛时间"]=PUBG["比赛时间"]//100


    我们先来看看特征与target的相关性

corr_target=PUBG.corr()["target"]
corr_target=corr_target.reset_index()
corr_target.columns=["features","target"]
corr_target=corr_target.sort_values(by="target",ascending=False)


3901436-cecb23601cd67354

    可以看见步行距离与target有这很高相关性,其次为嗑药数。

    可视化相关系数:


def bar(x,y):
    plt.figure(figsize=(8,11))
    plt.yticks(fontsize=20)
    sns.barplot(x,y)
bar(corr_target["target"],corr_target["features"])    

3901436-11ef2da2f1cb9fa9

    为了方便我们统计分析,小编把target==1,定义为“吃鸡”。

PUBG["target"]=PUBG["target"].apply(lambda x : 0 if x<1 else  1)
PUBG["target"].value_counts()   

3901436-786789f50e47c04f

def findnumric(df):
    types=pd.DataFrame(df.dtypes)
    numric=types[types[0]!="object"].index.tolist()
    return numric
name=findnumric(PUBG)
name 

    我们来看一下有哪些特征数属于数值型

3901436-ccabe8fcfcf06f6f

    对部分特征简单可视化。

def echarts_barplot(df,var,target):
    from pyecharts import Bar
    a=df.groupby([var])[target].mean().reset_index()
    b=df.groupby([var])[target].count().reset_index()
    b=b.merge(a,on=var,how="left").rename(columns={target+"_x":"counts",target+"_y":"rate"})
    group=b
    group=group.sort_index(by="counts",ascending=False)
    group["占比"]=group["counts"]/group["counts"].sum()
    group["累计"]=group["占比"].cumsum()
    bar = Bar("{}__吃鸡概率柱状图".format(var))
    bar.add("{}".format(var),  group[var],group["rate"])
    #bar.render()
    return bar

3901436-6126494e821f3df8
3901436-085c21987c42c15c
3901436-2bb4976531d3c684
3901436-8a35ac0d9df4c4e4
3901436-28b112d333f1f0c8
3901436-61155920206c3c90
3901436-6bd9012dd238327a
3901436-492c7330183aa1ac


    可以看见大部分特征均是随着数值升高,吃鸡概率也相应增加,跟相关性关系也比较吻合

3901436-63df0ea5b2492046


    比较有趣的事情是,有部分选手比较时间小于1分钟,落地成盒党最后的吃鸡概率竟然为100%。这个也说明有部分人是属于躺鸡状态,所以我们后期做特征工程的时候需要考虑其队友的数据。

    趣味分析:

    比如爆头率,按照常理来说,爆头率越高,代表枪法越准,吃鸡可能性可能会更大一下,但是事实上真的是这样吗?

3901436-90f8e182615076d6

    如上图,我们发现爆头率达到0.9以上的选手,最后吃鸡的概率大概在0.5,而爆头率只有0.07的选手吃鸡概率达到100%,或许数据未处理的图表看着不太准确,下面小编则用数据离散后的图表做分析

3901436-ced52df15f7cbff7

    由上图得知,分组为2的吃鸡概率最大,平均达到0.21,爆头率大于0.5的分组,最后的吃鸡概率仅为0.05。结论,过于追求完美的选手,用一句俗话,装逼被雷劈,把敌人杀死才最重要。小伙伴们,想吃鸡,就不要刻意追求爆头

    有些选手在玩吃鸡的时候,比较喜欢在路途中杀敌,抢“快递员”物质,抢得越多,物质越多,对最终的决赛越有利??这是真的吗??

3901436-0a89bc7c286714d9

    上图可以看出路杀率在[0.1,0.3)之间的小伙伴最终吃鸡概率最高,反而是那些喜欢堵桥啊,守点的选手吃鸡概率仅为0.025。这种情况很明显是吃鸡不成折把米,以为是别人给他送“快递”呢,真正的高手,都会选择尽快占领制高点,最终吃鸡也是顺理成章的事情。

maping={"squad-fpp":"squad",
       "duo-fpp":"duo",
       "solo-fpp":"solo",
       "duo":"duo",
       "solo":"solo",
       "normal-squad-fpp":"squad",
       "crashfpp":"other",
       "normal-duo-fpp":"duo",
       "flaretpp":"other",
       "normal-solo-fpp":"solo",
       "flarefpp":"other",
       "normal-duo-fpp":"duo",
       "normal-duo":"duo",
       "normal-squad":"squad",
       "crashtpp":"other",
       "normal-solo":"solo"}
PUBG["比赛类型"]=PUBG["比赛类型"].map(maping)

    小编把比赛类型进行重新分组

3901436-2b27a9302a337833

    不出意料,妥妥四排吃鸡概率最高。

    其余的数据,小编就不在这里详细分析了,有兴趣的小伙伴,做一个比较详细的EDA。言归正传,我们现在开始正式的特征工程。

def addfeature(train):
    train["爆头率"]=train["爆头杀敌"]/train["杀敌数"]
    train["短时间最大杀敌率"]=train["短时间最大杀敌"]/train["杀敌数"]
    train["路上杀敌数率"]=train["路上杀敌数"]/train["杀敌数"]
    train["误杀率"]=train["杀队友次数"]/train["杀敌数"]
    train["治疗+使用药品"]=train["治疗"]+train["使用药品"]
    train["总行动距离"]=train["车辆行驶距离"]+train["游泳距离"]+train["步行距离"]
    train["杀敌数排名/maxPlace"]=train["杀敌数排名"]/train["maxPlace"]
    train["爆头/杀敌数"]=train["杀敌数"]/train["爆头杀敌"]
    train["总行动距离/拾取武器"]=train["总行动距离"]/train["捡拾武器数"]
    train["步行距离/治疗"]=train["步行距离"]/train["治疗"]
    train["步行距离/杀敌数"]=train["步行距离"]/train["杀敌数"]
    train["步行距离/击倒数"]=train["步行距离"]/train["击倒数"]
    train["步行距离/使用药品"]=train["步行距离"]/train["使用药品"]
    train["步行距离/摧毁车辆数"]=train["步行距离"]/train["摧毁车辆数"]
    train["步行距离/车辆行驶距离"]=train["步行距离"]/train["车辆行驶距离"]
    train["步行距离/游泳距离"]=train["步行距离"]/train["游泳距离"]
    train["步行距离/使用药品"]=train["步行距离"]/train["使用药品"]
    train['杀敌数/步行距离'] = train['杀敌数'] / train['步行距离']
   train["车辆行驶距离/治疗"]=train["车辆行驶距离"]/train["治疗"]
    train["车辆行驶距离/杀敌数"]=train["车辆行驶距离"]/train["杀敌数"]
    train["车辆行驶距离/击倒数"]=train["车辆行驶距离"]/train["击倒数"]
    train["车辆行驶距离/使用药品"]=train["车辆行驶距离"]/train["使用药品"]
    train["车辆行驶距离/摧毁车辆数"]=train["车辆行驶距离"]/train["摧毁车辆数"]
    train["车辆行驶距离/车辆行驶距离"]=train["车辆行驶距离"]/train["车辆行驶距离"]
    train["车辆行驶距离/游泳距离"]=train["车辆行驶距离"]/train["游泳距离"]
    train["车辆行驶距离/使用药品"]=train["车辆行驶距离"]/train["使用药品"]
    train['杀敌数/车辆行驶距离'] = train['杀敌数'] / train['车辆行驶距离']
   train["击倒数/杀敌数"]=train["击倒数"]/train["杀敌数"]
    train["击倒数/助攻数"]=train["击倒数"]/train["助攻数"]
    train["击倒数/爆头杀敌"]=train["击倒数"]/train["爆头杀敌"]
    train["击倒数-杀敌数"]=np.abs(train["击倒数"]-train["杀敌数"])
    train["杀敌数-短时间最大杀敌"]=np.abs(train["杀敌数"]-train["短时间最大杀敌"])
    train["助攻数/击倒数"]=train["助攻数"]/train["击倒数"]
    train["助攻数-杀敌数"]=np.abs(train["助攻数"]-train["杀敌数"])
    train["爆头+路杀"] = train["爆头杀敌"] + train["路上杀敌数"]
   train["总伤害/杀敌数"]=train["总伤害"]/train["杀敌数"]
    train["总伤害/助攻数"]=train["总伤害"]/train["助攻数"]
    train["总伤害/短时间最大杀敌"]=train["总伤害"]/train["短时间最大杀敌"]
    train["总伤害/路上杀敌数"]=train["总伤害"]/train["路上杀敌数"]
    train["总伤害/爆头杀敌"]=train["总伤害"]/train["爆头杀敌"]
    train["总伤害/击倒数"]=train["总伤害"]/train["击倒数"]
    train["总伤害/治疗"]=train["总伤害"]/train["治疗"]
   train["使用药品-杀敌数"]=np.abs(train["使用药品"]-train["杀敌数"])
    train["使用药品/杀敌数"]=train["使用药品"]/train["杀敌数"]
    train["使用药品/治疗"]=train["使用药品"]/train["治疗"]
    train["使用药品-治疗"]=np.abs(train["使用药品"]-train["治疗"])
    train["车辆行驶距离/路上杀敌数"]=train["车辆行驶距离"]/train["路上杀敌数"]
    train["助攻数/杀敌数"]=train["助攻数"]/train["杀敌数"]
    train["杀敌数/助攻数"]=train["杀敌数"]/train["助攻数"]
    train["杀敌数/捡拾武器数"]=train["杀敌数"]/train["捡拾武器数"]
    train["捡拾武器数/杀敌数"]=train["捡拾武器数"]/train["杀敌数"]
    train["比赛时间1"]=train["比赛时间"]//100
    train["死亡前最大时间"]=train["死亡前最大时间"]/100
    train["比赛时间/杀敌数"]=train["比赛时间1"]/train["杀敌数"]
    train["比赛时间/击倒数"]=train["比赛时间1"]/train["击倒数"]
    train["比赛时间/爆头杀敌"]=train["比赛时间1"]/train["爆头杀敌"]
    train["比赛时间/路上杀敌数"]=train["比赛时间1"]/train["路上杀敌数"]
    train["死亡前最大时间/比赛时间"]=train["死亡前最大时间"]/train["比赛时间1"]
    print("Removing Na's From DF")
    train[train == np.inf] = np.NaN
    train[train == np.NINF] = np.NaN
    train.fillna(0, inplace=True)
    features = list(train.columns)
    target = "target"
   if target in features:  
        y=train[target]
        features.remove(target)
        train=train[features]
   else:
        y=None
        train=train[features]


#自己流弊不流弊不重要,重要的是跟对队友才重要,现在计算组队情况    
    feature=['助攻数', '使用药品', '总伤害', '击倒数', '爆头杀敌', '治疗',
       '杀敌数排名', '杀敌数外部排名', '杀敌数', '短时间最大杀敌', '比赛时间', 
        'Elo玩家排名', '路上杀敌数', '积分','总行动距离','捡拾武器数',"死亡前最大时间"]
    print("group mean")
    start=time.time()
    agg = train.groupby(['matchId','groupId'])[feature].agg('mean').reset_index()
    train=train.merge(agg, suffixes=["", "_mean"], how='left', on=['matchId','groupId'])
    print("preparing rank ...")
    agg_rank = train.groupby(['matchId','groupId'])[feature].agg('min').rank(pct=True).reset_index()
    print("rank complete")
    train = train.merge(agg_rank, suffixes=["", "_mean_rank"], how='left', on=['matchId', 'groupId'])
    end=time.time()
    print("cost time {:.2f}mins".format((end-start)/60))
    del agg ,agg_rank
    gc.collect()
    print("group min")
    start=time.time()
    agg = train.groupby(['matchId','groupId'])[feature].agg('min').reset_index()
    train=train.merge(agg, suffixes=["", "_min"], how='left', on=['matchId','groupId'])
    print("preparing rank ...")
    agg_rank = train.groupby(['matchId','groupId'])[feature].agg('min').rank(pct=True).reset_index()
    print("rank complete")
    train = train.merge(agg_rank, suffixes=["", "_min_rank"], how='left', on=['matchId', 'groupId'])
    end=time.time()
    print("cost time {:.2f}mins".format((end-start)/60))
    del agg ,agg_rank
    gc.collect()
    print("group max")
    start=time.time()
    agg = train.groupby(['matchId','groupId'])[feature].agg('max').reset_index()
    train=train.merge(agg, suffixes=["", "_max"], how='left', on=['matchId','groupId'])
    print("preparing rank ...")
    agg_rank = train.groupby(['matchId','groupId'])[feature].agg('max').rank(pct=True).reset_index()
    print("rank complete")
    train = train.merge(agg_rank, suffixes=["", "_max_rank"], how='left', on=['matchId', 'groupId'])
    end=time.time()
    print("cost time {:.2f}mins".format((end-start)/60))
    del agg ,agg_rank
    gc.collect()
    print("group size")
    start=time.time()
    agg = train.groupby(['matchId','groupId'])[feature].size().reset_index()
    train=train.merge(agg, suffixes=["", "_size"], how='left', on=['matchId','groupId'])
    print("preparing rank ...")
    agg_rank = train.groupby(['matchId','groupId'])[feature].agg('size').rank(pct=True).reset_index()
    print("rank complete")
    train = train.merge(agg_rank, suffixes=["", "_size_rank"], how='left', on=['matchId', 'groupId'])
    end=time.time()
    print("cost time {:.2f}mins".format((end-start)/60))
    del agg ,agg_rank
    gc.collect()
    print("group sum")
    start=time.time()
    agg = train.groupby(['matchId','groupId'])[feature].agg('sum').reset_index()
    train=train.merge(agg, suffixes=["", "_sum"], how='left', on=['matchId','groupId'])
    print("preparing rank ...")
    agg_rank = train.groupby(['matchId','groupId'])[feature].agg('sum').rank(pct=True).reset_index()
    print("rank complete")
    train = train.merge(agg_rank, suffixes=["", "_sum_rank"], how='left', on=['matchId', 'groupId'])
    end=time.time()
    print("cost time {:.2f}mins".format((end-start)/60))
    del agg ,agg_rank
    gc.collect()
    variable=list(train.columns)
    variable.remove("Id")
    variable.remove("matchId")
    variable.remove("groupId")
    variable.remove("比赛类型")
    train=train[variable]
    return train, y


def reduce_mem_usage(df):
    """ iterate through all the columns of a dataframe and modify the data type
        to reduce memory usage.        
    """
    start_mem = df.memory_usage().sum() 
    print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))
   for col in df.columns:
        col_type = df[col].dtype
       if col_type != object:
            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)
        else:
            df[col] = df[col].astype('category')

    end_mem = df.memory_usage().sum() 
    print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
    print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
   return df

3901436-417bd52be35408e6
3901436-529ed80d0b5e8439
3901436-68b6ebb48d93aa2e

        一般数据需要分为训练集跟测试集,有时候数据划分的好坏,直接决定模型的结果。我们先来看一下不交叉验证的模型算法结果。

train_X,val_X,train_y,val_y=train_test_split(train,y,test_size=0.3)
def run_lgb(train_X, train_y, val_X, val_y, x_test):
    params = {"objective" : "regression", "metric" : "mae", 'n_estimators':20000, 'early_stopping_rounds':200,
              "num_leaves" : 50, "learning_rate" : 0.05, "bagging_fraction" : 0.7,"max_depth":-1,
               "bagging_seed" : 0, "num_threads" : 4,"colsample_bytree" : 0.7
             }

    lgtrain = lgb.Dataset(train_X, label=train_y)
    lgval = lgb.Dataset(val_X, label=val_y)
    model = lgb.train(params, lgtrain, valid_sets=[lgtrain, lgval], early_stopping_rounds=200, verbose_eval=100)

    pred_test_y = model.predict(x_test, num_iteration=model.best_iteration)
    return pred_test_y, model

3901436-9bcdbb288535f210

小编在这里迭代两万步,最后mase得分在0.0378831

lgb_model = lgb.LGBMClassifier(boosting_type='gbdt', num_leaves=100, reg_alpha=3, reg_lambda=5, max_depth=-1,
    n_estimators=8000, objective='binary', subsample=0.9, colsample_bytree=0.77, subsample_freq=1, learning_rate=0.02,
    random_state=1000, n_jobs=16, min_child_weight=4, min_child_samples=5, min_split_gain=0)
skf = StratifiedKFold(n_splits=5, random_state=2018, shuffle=True)
best_score = []

oof_preds = np.zeros(train.shape[0])

for index, (train_index, test_index) in enumerate(skf.split(train, y)):
    lgb_model.fit(train.iloc[train_index], y.iloc[train_index], verbose=50,
                  eval_set=[(train.iloc[train_index], y.iloc[train_index]),
                            (train.iloc[test_index], y.iloc[test_index])], early_stopping_rounds=30)
    best_score.append(lgb_model.best_score_['valid_1']['binary_logloss'])
    print(best_score)
    oof_preds[test_index] = lgb_model.predict_proba(train.iloc[test_index], num_iteration=lgb_model.best_iteration_)[:,1]


3901436-75781af449dfc9f6

    利用交叉验证,对结果取平均,迭代8000次的时候,loss已经达到0.028289,效果比之前明显好很多,而且在8000步的时候并没有early_stopping,其实还有下降空间。小编并没有对数据做特征筛选,特征工程也只是各种无脑加,做特征筛选后,效果可能会更好一点,这里就不做了。

    吃鸡结论:不要爆头,不要当拦路虎,多四排,大吉大利,今晚吃鸡!!!



Python的爱好者社区历史文章大合集

2018年Python爱好者社区历史文章合集(作者篇)

2018年Python爱好者社区历史文章合集(类型篇)

3901436-b5b6beb5ec170796

关注后在公众号内回复“ 课程 ”即可获取:

小编的转行入职数据科学(数据分析挖掘/机器学习方向)【最新免费】

小编的Python的入门免费视频课程

小编的Python的快速上手matplotlib可视化库!

崔老师爬虫实战案例免费学习视频。

陈老师数据分析报告扩展制作免费学习视频。

玩转大数据分析!Spark2.X + Python精华实战课程免费学习视频。

3901436-7c3e2d33949762e7
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值