Команда PUBG предоставляет данные о 65к игр и просит предсказать место, которое займет игрок.
Я хочу показать самые первые шаги, когда к вам в руки попадают данные
Ну шо, погнали
Для начала давайте взглянем на данные
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
data = pd.read_csv('train_V2.csv')
data.head(5)
Каждый уважающий себя Data Scientist должен скролить csv вправо, затем влево, бурча себе под нос "suka blat chto eto za huyna"
Когда этот ритуал неувенчался успехом, следует почитать описание признаков
DBNOs - Number of enemy players knocked.
assists - Number of enemy players this player damaged that were killed by teammates.
boosts - Number of boost items used.
damageDealt - Total damage dealt. Note: Self inflicted damage is subtracted.
headshotKills - Number of enemy players killed with headshots.
heals - Number of healing items used.
Id - Player’s Id
killPlace - Ranking in match of number of enemy players killed.
killPoints - Kills-based external ranking of player. (Think of this as an Elo ranking where only kills matter.) If there is a value other than -1 in rankPoints, then any 0 in killPoints should be treated as a “None”.
killStreaks - Max number of enemy players killed in a short amount of time.
kills - Number of enemy players killed.
longestKill - Longest distance between player and player killed at time of death. This may be misleading, as downing a player and driving away may lead to a large longestKill stat.
matchDuration - Duration of match in seconds.
matchId - ID to identify match. There are no matches that are in both the training and testing set.
matchType - String identifying the game mode that the data comes from. The standard modes are “solo”, “duo”, “squad”, “solo-fpp”, “duo-fpp”, and “squad-fpp”; other modes are from events or custom matches.
rankPoints - Elo-like ranking of player. This ranking is inconsistent and is being deprecated in the API’s next version, so use with caution. Value of -1 takes place of “None”.
revives - Number of times this player revived teammates.
rideDistance - Total distance traveled in vehicles measured in meters.
roadKills - Number of kills while in a vehicle.
swimDistance - Total distance traveled by swimming measured in meters.
teamKills - Number of times this player killed a teammate.
vehicleDestroys - Number of vehicles destroyed.
walkDistance - Total distance traveled on foot measured in meters.
weaponsAcquired - Number of weapons picked up.
winPoints - Win-based external ranking of player. (Think of this as an Elo ranking where only winning matters.) If there is a value other than -1 in rankPoints, then any 0 in winPoints should be treated as a “None”.
groupId - ID to identify a group within a match. If the same group of players plays in different matches, they will have a different groupId each time.
numGroups - Number of groups we have data for in the match.
maxPlace - Worst placement we have data for in the match. This may not match with numGroups, as sometimes the data skips over placements.
winPlacePerc - The target of prediction. This is a percentile winning placement, where 1 corresponds to 1st place, and 0 corresponds to last place in the match. It is calculated off of maxPlace, not numGroups, so it is possible to have missing chunks in a match.
Так уже лучше, теперь мы понимаем, что целевой признак "winPlacePerc", и он распределен от 0 до 1, это конечно же нам наруку. Перед нами типичная задача регрессии
Посмотрим общую информацию о признаках
print(data.info())
print(data.shape)
В нашем распоряжении 29 бравых солдат, 4 из которых категорильные
Еще немного информации
data.describe()
Один чувак из команды PUBG сказал, что в этом датасете есть один перец, который единственый зашел на матч и для него нет целевого признака, давайте найдем этого победителя по жизни
np.sum(data.isnull())
data[data['winPlacePerc'].isnull()]
Вот он красавец, благополучно дропаем его без всяких сожалений
data.drop(data[data['winPlacePerc'].isnull()].index.values, inplace=True)
Итак, с чего бы я начал анализ этих данных? Раз это игра, значит в ней обязательно есть либо багаюзеры, либо читеры, либо еще какие-нибудь черти, которые портят или искажают игровой процесс, эти pidori обязательно ухудшат качество модели, так что давайте искать АНОМАЛИИ
Сегодня я сильно не буду вдаваться в Feature Engineering, но создать эту пару признаков все же считаю своим долгом
Люди, которые не двигались всю игру и кого-то настреляли полюбому нечистые на душу
data['totalDistance'] = data['rideDistance'] + data['walkDistance'] + data['swimDistance']
data['killsWithoutMoving'] = ((data['kills'] > 0) & (data['totalDistance'] == 0))
Посмотрим на этих петухов
display(data[data['killsWithoutMoving']].head(5))
print('размерность:', data[data['killsWithoutMoving']].shape)
Давайте до свидания
data.drop(data[data['killsWithoutMoving'] == True].index, inplace=True)
Так, давайте следующий подозрительный признак
plt.figure(figsize=(10, 5))
sns.countplot(data['roadKills'])
plt.show()
data['roadKills'].value_counts()
data[data['roadKills'] > 10]
Чуваков, которые зашли поиграть в Need for speed, мы тоже кикаем, особенно угарный c3e444f7d1289f, который проехал 5 метров и задавил 14 тел. Окей, пока
data.drop(data[data['roadKills'] > 10].index, inplace=True)
Теперь перейдем к самому очевидному признаку, который стоит проверить, убийствам
plt.figure(figsize=(10,5))
sns.distplot(data['kills'],bins=15)
plt.show()
Pizdec, больше 70 убийств при 100 игроках? Это точно читеры, на корм рыбам
display(data[data['kills'] > 30].head(5))
print(data[data['kills'] > 30].shape)
data.drop(data[data['kills'] > 30].index, inplace=True)
Есть еще кое какой подозрительный признак, longestKill - дистанция при убийстве, давайте взглянем
plt.figure(figsize=(10,5))
sns.distplot(data['longestKill'], bins=15)
plt.show()
Основная масса - это убийства на ~100 метрах, чуваки, убивающие с 1км+, что вы такое?
display(data[data['longestKill'] > 1000].head(5))
print(data[data['longestKill'] > 1000].shape)
Боюсь, придется пожертвовать этими элитными снайперами
data.drop(data[data['longestKill'] > 1000].index, inplace=True)
Давайте переходить к гонщикам наскар, марафонцам и водолазам
Посмотрим, сколько игроки накатывают на тачках за игру
plt.figure(figsize=(10,5))
sns.distplot(data['rideDistance'], bins=15)
plt.show()
display(data[data['rideDistance'] > 20000].head(5))
print(data[data['rideDistance'] > 20000].shape)
150 человек просто катаются всю игру по карте
Избавляемся от них по наработанной схеме
data.drop(data[data['rideDistance'] > 20000].index, inplace=True)
Теперь к дайверам
plt.figure(figsize=(10,5))
sns.distplot(data['swimDistance'], bins=15)
plt.show()
display(data[data['swimDistance'] > 2000].head(5))
print(data[data['swimDistance'] > 2000].shape)
Чтоб вы понимали как это выглядит
и так всю игру, тоже удаляем
data.drop(data[data['swimDistance'] > 2000].index, inplace=True)
Пешие
Все стандартно
plt.figure(figsize=(10,5))
sns.distplot(data['walkDistance'], bins=15)
plt.show()
display(data[data['walkDistance'] > 10000].head(5))
print(data[data['walkDistance'] > 10000].shape)
data.drop(data[data['walkDistance'] > 10000].index, inplace=True)
А вот еще забавный признак weaponsAcquired - сколько оружий поднял игрок за матч
plt.figure(figsize=(10,5))
sns.distplot(data['weaponsAcquired'], bins=15)
plt.show()
Зачем подбирать более 100 оружий? Не знаете? Я тоже не знаю, но они мне не нравятся
Голову с плеч
display(data[data['weaponsAcquired'] > 80].head(5))
print(data[data['weaponsAcquired'] > 80].shape)
data.drop(data[data['weaponsAcquired'] > 80].index, inplace=True)
Ну и последний признак, который мы сегодня рассмотрим heals
plt.figure(figsize=(10,5))
sns.distplot(data['heals'], bins=15)
plt.show()
Уф
Эти ребята точно что-то скрывают, посмотрим на них
display(data[data['heals'] > 40].head(5))
print(data[data['heals'] > 40].shape)
дааа, явно что-то не так, убираем
data.drop(data[data['heals'] > 40].index, inplace=True)
data.shape
Мы удалили более 2000 игроков и исключили практически все аномалии из данных, неплохой старт, конечно же это не вся работа, которую надо проделать, но начало положено, за тобой Feature Engineering, подбор алгоритма и т.д.
Гуд лак