吃鸡攻略

浏览: 1995

作者:海笛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()

    

    比赛时间为千位数,为了方便大家认知,把时间除以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)

    可以看见步行距离与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"])    

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

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

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

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

    对部分特征简单可视化。

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

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

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

    趣味分析:

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

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

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

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

    上图可以看出路杀率在[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)

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

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

    其余的数据,小编就不在这里详细分析了,有兴趣的小伙伴,做一个比较详细的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

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

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

小编在这里迭代两万步,最后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]

    

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

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

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

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

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

福利:文末扫码关注公众号,“Python爱好者社区”,开始学习Python课程:

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

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

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

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

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

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

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

推荐 0
本文由 Python爱好者社区 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册