数ある記事の中からこのページを開いてくださりありがとうございます。
就労移行支援施設でpythonなどの勉強をしています。
第2回目の投稿ということで初心者の初心者による初心者のためのデータ分析!League of Legendsで下克上を目指せ!(穴場のチャンピオン探し編)の続きをあげていきます。
League of Legends(以後lol)をテーマに分析を始めた経緯は前回の記事をご覧ください。
前回やったことと今回やること
前回はlolで採用率はあまり高くないけれども勝率の高い「穴場」のキャラクター(以後チャンピオン)チャンピオンを過去の試合データを基に分析してみました。
そこではブルーのミッドレーンを対象にし採用率の高いチャンピオン上位20位までを出したところ最も採用率の高かったチャンピオンはOriannaで採用率は約8.43%で勝率は約53.0%でした。
一方で採用率では最下位のMalzaharの採用率は約1.71%と決して高くないものの勝率は約64.1%で全20チャンピオンの中で最上位でした。
しかし何年もプレイしている人はどういったチャンピオンが使われているか把握しておりOriannaの対策は既にできている可能性があります。その対抗策としてMalzaharのようなあまり使われていないけれど勝率の高いチャンピオンを使うことで盲点をつける可能性がないかと考えたのです。
しかしこれにも弱点があります。
各プレイヤーが普段どのチャンピオンを使っているかネット上で研究できるので本番の時BANされる危険があります。
そのため第2第3候補も作っておき柔軟に対応できるようにしていく必要があります。
そこで考えたのは自分がよく選ぶチャンピオンを使うプレイヤーは他にどういったチャンピオンを使っているか明らかにすることです。
そこで出力されたチャンピオンで前回の表にも登場しているものがあれば代替案としてある程度信頼の置けるものとなります。
ではどうやってやるか
誰がどのチャンピオンを使っているか、他にどのチャンピオンを使っているか1つ1つ見ていくとなると時間がいくらあっても足りません。
そこで今回は機械学習を使います。
検証開始!
データを確認し使える状態に直す
前回と同様にデータを読み込みいらない情報はカットします。
import pandas as pd
import numpy as np
from scipy.sparse import csr_matrix
from sklearn.neighbors import NearestNeighbors
whole_data = pd.read_csv('matchinfo.csv')
player_info = whole_data[["blueMiddle", "blueMiddleChamp"]]
#今回はブルーのミッドレーンを担当したユーザーの名前と使ったチャンピオンのデータだけ使う
player_info.describe()
これでいらないデータはカットできたので概観を確認してみましょう。
総プレイヤーの数が多すぎると一人当たりの出場した試合数が少ないということになり「傾向」を掴むのが難しくなるからです。
blueMiddle | blueMiddleChamp | |
---|---|---|
count | 7583 | 7620 |
unique | 322 | 71 |
top | Faker | Orianna |
freq | 177 | 643 |
使われたチャンピオンの数は71種類。
プレイヤーの数は322人なので一人当たりの出場回数といった懸念事項は大丈夫そうです。
一方で困ったことにblueMiddleとblueMiddleChampでデータの個数が違うので欠損があると見られます。
ちょっと見てみましょう。
player_info.isnull().sum()
blueMiddle 37
blueMiddleChamp 0
isnull().sum()を使い2つの項目でどちらにどの欠損があるか調べてみました。
これによるとユーザーの名前でわからないものがあるようです。
player_info = player_info.dropna()
player_info.describe()
player_info.isnull().sum()
blueMiddle | blueMiddleChamp | |
---|---|---|
count | 7583 | 7583 |
unique | 322 | 71 |
top | Faker | Orianna |
freq | 177 | 643 |
blueMiddle 0
blueMiddleChamp 0
dropna()を用いて欠損データを除外し綺麗な状態になっているか確認しました。
これで大丈夫ですしプレイヤーやチャンピオンの種類に支障はなさそうです。
さらなるデータ加工で新しい表を作成!
次に各チャンピオンがどのユーザーに使われているかを可視化する必要があります。
アマゾンやネットフリックスを例にしましょう。
ユーザーごとに違った商品や作品が出てくるのは誰が何をどれくらい評価しているかを詳細に記録しておりそこからどれを売ればお金を落としてもらえる傾向にあるかプログラムが学習してくれているからです。
今回は評価を各ユーザーに選ばれた回数としデータ処理を進めていきます。
player_info["usage"] = 1
player_info.head()
blueMiddle | blueMiddleChamp | usage | |
---|---|---|---|
0 | Bjergsen | Ahri | 1 |
1 | Jesiz | Ahri | 1 |
2 | Pobelter | Fizz | 1 |
3 | XiaoWeiXiao | Leblanc | 1 |
4 | Link | Lissandra | 1 |
先程の表にusageを追加しました。
一回の試合で1つのチームから同じチャンピオンを2体以上使われることはないので一律で1としています。
次はユーザーとチャンピオンの組み合わせで全く同じものをひとまとめにしusageを2,3...とまとめていきます。
player_info = player_info.groupby(["blueMiddle", "blueMiddleChamp"])["usage"].sum().reset_index()
player_info.head(5)#最初から数え5つまで表示
blueMiddle | blueMiddleChamp | usage | |
---|---|---|---|
0 | Abaria | Azir | 3 |
1 | Abaria | Corki | 1 |
2 | Abaria | Karma | 2 |
3 | Abaria | Kassadin | 1 |
4 | Abaria | Leblanc | 2 |
これで各ユーザーがどのチャンピオンを使っているかの回数をまとめるのに成功しました。
さらに加工し縦軸はチャンピオン名、横軸をユーザーという形の表を作っていきます。
player_info_pivot = player_info.pivot(index= 'blueMiddleChamp',columns='blueMiddle',values='usage').fillna(0)
player_info_pivot_sparse = csr_matrix(player_info_pivot.values)
blueMiddle | Abaria | Abbedagge | Abou222 | Ace |
---|---|---|---|---|
blueMiddleChamp | ||||
Ahri | 0.0 | 0.0 | 0.0 | 0.0 |
Akali | 0.0 | 0.0 | 0.0 | 0.0 |
Anivia | 0.0 | 0.0 | 0.0 | 0.0 |
AurelionSol | 0.0 | 0.0 | 0.0 | 0.0 |
Azir | 3.0 | 0.0 | 0.0 | 2.0 |
pivot()を用いて各チャンピオンに対し誰がどれくらい使っているかを表にできました。
ここで表示させているのはごく一部です。
AbariaというプレイヤーはAzirを3回使っていることがわかります。
他の項目で0.0になっているのは一度も使われていないことを意味しています。
機械学習開始!
今回作ったデータをk近傍法という機械学習の手法を使って学習させます。
簡単にいうと今回学習させた中で特定のチャンピオンを指定した時にそれと最も近い距離にあるチャンピオンを割出してくれます。
これによって指定したチャンピオンを使っているユーザーは他にどのチャンピオンを使っているか見ることができます。
前回採用率の低さに対し高い勝率を誇っていたMalzaharで見てみましょう。
knn = NearestNeighbors(n_neighbors=9,algorithm= 'brute', metric = 'cosine')
model_knn = knn.fit(player_info_pivot_sparse)
Champion = "Malzahar"
distance, indice = model_knn.kneighbors(player_info_pivot.iloc[player_info_pivot.index==Champion].values.reshape(1, -1),n_neighbors=11)
for i in range(0, len(distance.flatten())):
if i == 0:
print('Recommendations if you use the champion {0}:\n'.format(player_info_pivot[player_info_pivot.index== Champion].index[0]))
else:
print('{0}: {1} with distance: {2}'.format(i,player_info_pivot.index[indice.flatten()[i]],distance.flatten()[i]))
ここで出た結果は以下の通りです。
Recommendations if you use the champion Malzahar:
1: Viktor with distance: 0.34904342083186113
2: Taliyah with distance: 0.3723002696233345
3: Karma with distance: 0.42070673240848855
4: Azir with distance: 0.44118057612305706
5: Corki with distance: 0.4434960701685541
6: Ryze with distance: 0.47858784720918135
7: Vladimir with distance: 0.47906757547291845
8: Cassiopeia with distance: 0.4950791597239671
9: Varus with distance: 0.5029226155596387
10: AurelionSol with distance: 0.5217205327935888
学習させたものを基に指定したチャンピオンから距離の近いもの上位10位までを表すことに成功しました。
チャンピオン名の後に"with distance:"で指定したチャンピオンとの距離を表しています。 0に近いほど近い距離になります。
ここで前回の記事で作成した表と見比べてみましょう。
blueMiddleChamp | Num of Selected | Selected Rate | Total Winning | Winning Rate |
---|---|---|---|---|
Orianna | 643 | 8.438320 | 341 | 53.032659 |
Viktor | 621 | 8.149606 | 298 | 47.987118 |
Syndra | 526 | 6.902887 | 299 | 56.844106 |
Azir | 489 | 6.417323 | 285 | 58.282209 |
Corki | 446 | 5.853018 | 232 | 52.017937 |
Leblanc | 421 | 5.524934 | 221 | 52.494062 |
Cassiopeia | 391 | 5.131234 | 217 | 55.498721 |
Taliyah | 388 | 5.091864 | 236 | 60.824742 |
Ryze | 366 | 4.803150 | 208 | 56.830601 |
Ahri | 334 | 4.383202 | 185 | 55.389222 |
Vladimir | 311 | 4.081365 | 160 | 51.446945 |
Lulu | 225 | 2.952756 | 119 | 52.888889 |
Lissandra | 199 | 2.611549 | 114 | 57.286432 |
Zed | 183 | 2.401575 | 112 | 61.202186 |
Jayce | 180 | 2.362205 | 89 | 49.444444 |
Kassadin | 167 | 2.191601 | 90 | 53.892216 |
Galio | 154 | 2.020997 | 81 | 52.597403 |
Karma | 153 | 2.007874 | 72 | 47.058824 |
TwistedFate | 153 | 2.007874 | 79 | 51.633987 |
Malzahar | 131 | 1.719160 | 84 | 64.122137 |
比較してみるとレコメンドで1位になっているViktorなど前回の表と合致するものもいることがわかります。
これらを照合し「低めの採用率だけど高い勝率」「本命のチャンピオンを使っているユーザーが他に選ぶもの」を軸に複数の候補を用意することで、相手のBANで戦力を一気に削がれるというリスクを下げることができます。
おわりに
「採用率は低いけど勝率の高いチャンピオン」の続きで、自分が使おうと思っているチャンピオンがBANされた場合の代替案を見つけるプログラムを作りました。
そのために機械学習を用いており、例えばMalzaharを使っているユーザーは他にどういったチャンピオンを選んでいるかを出力させています。
そこには前回まとめた採用率の高いチャンピオン上位20位に入るものもあり照合した上でどのように第2第3候補を選んでいくかが鍵になります。
前回と今回では「チャンピオン選び」というところからの簡単な分析だったので引き続き分析をし、できたものからあげていきます。