機械学習、Python、GridDBを用いたサッカー選手のレコメンデーションシステム

サッカービジネスは、高いパフォーマンスを発揮するアスリート、熱狂的なファン、そして大きなスポンサー契約を組み合わせた数十億ドル規模の産業です。世界中のチーム・オーナーやマネージャーは、自分たちのチームに勝利のサッカーをもたらすことができる最高の人材を見つけるために、常にエッジを探しています。チームマネージャーがバランスの取れた優秀なチームを見つけるために機械学習を利用することは、ビジネスに付加価値を与えるテクノロジーとデータの完璧な組み合わせです。

この記事では、マネージャーが才能ある選手や有望な選手を見つけるのに役立つレコメンデーションシステムモデルについて、彼らのパフォーマンスとサッカーリーグのデータに基づいて紹介します。その目的は、レオk面デーションシステムを、革新的で高いパフォーマンスを発揮するサッカー選手を見つけるためのモニタリングやプロスペクティングツールとして利用することです。本ブログでは、PythonとGridDBを用いて、サッカーの試合データからサッカー選手を推薦するレコメンデーションシステムモデルを提案します。

ソースコードはこちらからダウンロードしてください。

```sh
$ git clone https://github.com/griddbnet/Blogs.git --branch soccer
```

## 環境の設定

この記事で説明するレコメンデーションシステムを実装するには、まずPythonコードを正しく実行できるようにマシンの環境を設定することから始めます。以下は、あなたの環境で満たさなければならない前提条件の一部です。

*   **GridDB:** [GridDB][1]はレコメンデーションシステムモデルで使用するデータを格納するデータベースです。
*   **Python 3.11.2:** このソリューションでは最新バージョンの[Python 3.11.2][2]を使用しています。
*   **Jupyter Notebook:** [Jupyter Notebook][3]はPythonコードを実行するための統合開発環境（IDE）です。

不足しているパッケージをインストールする必要がある場合は、コマンドラインから次のように入力してインストールすることができます。

```sh
pip install package-name
```

また、GridDBを利用する場合は、これらの追加ライブラリを入手する必要があります。

1.  [GridDB Cクライアント][4]
2.  [GridDB Pythonクライアント][5]

最後に、[GridDB Pythonクライアントライブラリ][6] が不足しています。ここでは、Jupyterのターミナルでpipコマンドを使って不足しているライブラリをインストールします。

```sh
pip install griddb-python
```

環境のインストールと設定に成功したら、データセットを探索しましょう。

## データセットの紹介

本ブログで使用したデータセットには、**416**行、**17**列が含まれています。このデータセットは、サッカー選手をその役割と歴史的功績の観点から定義する属性で構成されています。これらの属性は、現在の市場価値、フィールドポジション、得点などを考慮したものです。

以下は、我々のデータセットに見られる特徴のリストになります。

*   **Name:** 選手の名前 (テキスト値)
*   **Club:** クラブ名 (テキスト値)
*   **Age:** 選手の年齢 (数値)
*   **Position:** 選手のフィールドポジション (テキスト値)
*   **Position Category:** 選手のフィールドポジションのカテゴリ変数 (数値)
*   **Market Value:** 選手の市場価値 (数値)
*   **Page Views:** 1 日当たりのウィキペディアのページビュー数
*   **Fantasy League Value:** ファンタジープレミアリーグにおける選手の市場価値 (数値)
*   **Fantasy League Selection:** ファンタジープレミアリーグにおいて選手が選ばれた割合 (数値)
*   **Fantasy League Points:** ファンタジープレミアリーグにおける選手のポイント (数値)
*   **Region:** 選手の地域を表すカテゴリ変数 (数値)
*   **Nationality:** 選手の国籍 (テキスト値)
*   **New Foreign:** 選手が新たに海外のクラブと契約したか否か (真理値)
*   **Age Category:** 選手の年齢層を示すカテゴリ変数 (数値)
*   **Club ID:** クラブの識別子 (数値)
*   **Big Club:** 選手が有名クラブと契約したか否か (真理値)
*   **New Signing:** 選手が新たにクラブと契約したか否か (真理値)

データセットは[イングランド・プレミアリーグ選手のデータセット][7]から抽出しました。 下の表は、このデータセットの最初の**3**行です。

![image][8]

## **必要なライブラリをインポートする**

この記事では、複数のPythonモジュールを使用し、その用途に応じてインポートすることで、レコメンデーションシステムを構築します。

*   データセットの読み込みと前処理に使用されるPythonライブラリ

```python
import numpy as np 
import pandas as pd
```

*   Pythonのライブラリは、グラフやプロットを使ってデータセットを探索するために使われます。

```python
import seaborn as sns
import matplotlib.pyplot as plt
```

*   レコメンデーションシステムモデルを構築するために使用されるPythonライブラリ

```python
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import NearestNeighbors
from sklearn.decomposition import PCA
```

*   GridDBクラスタに接続するためのPythonライブラリ

```python
import griddb_python as griddb
```

必要なライブラリのインポートに成功したら、まず **イングランド・プレミアリーグ選手のデータセット** を読み込みます。

## **データセットの読み込み**

GridDBは、データセットを保存するために使用するデータ・ストレージ・メカニズムであるため、我々のレコメンデーションシステムを構築する上で重要な役割を果たします。データを正常に格納するために、まず GridDB コンテナをロードします。これは、先ほどインストールした `griddb_python` ライブラリを使って行うことができます。次に、**container.put** を使ってループを使ってデータを挿入します。これが終わったら、データをデータフレームにロードして、レコメンデーションシステムの作成を続けなければなりません。

このセクションで説明するコードは次のように書くことができます。

```python
factory = griddb.StoreFactory.get_instance()

# Provide the necessary arguments
gridstore = factory.get_store(
    notification_member = '127.0.0.1:10001',
    cluster_name = 'myCluster',
    username = 'admin',
    password = 'admin'
)

# Define the container info
conInfo = griddb.ContainerInfo(
    "football_players",
    [
        ["name", griddb.Type.STRING],
        ["club", griddb.Type.STRING],
        ["age", griddb.Type.DOUBLE],
        ["position", griddb.Type.STRING],
        ["position_cat", griddb.Type.DOUBLE],
        ["market_value", griddb.Type.DOUBLE],
        ["page_views", griddb.Type.DOUBLE],
        ["fpl_value", griddb.Type.DOUBLE],
        ["fpl_sel", griddb.Type.STRING],
        ["fpl_points", griddb.Type.DOUBLE],
        ["region", griddb.Type.DOUBLE],
        ["nationality", griddb.Type.STRING],
        ["new_foreign", griddb.Type.DOUBLE],
        ["age_cat", griddb.Type.DOUBLE],
        ["club_id", griddb.Type.DOUBLE],
        ["big_club", griddb.Type.DOUBLE],
        ["new_signing", griddb.Type.DOUBLE]
    ],
    griddb.ContainerType.COLLECTION, True
)

# Drop container if it exists
gridstore.drop_container(conInfo.name)

# Create a container
container = gridstore.put_container(conInfo)

# Load the data

# Put rows
for i in range(len(data)):
  row = data.iloc[i].tolist()
  try:
    container.put(row)
  except Exception as e:
    print(f"Error on row {i}: {row}")
    print(e)

cont = gridstore.get_container("football_players")

if cont is None:
  print("Does not exist")

print("connection successful")

# Define the exact columns you need
columns = ["*"]

select_statement = "SELECT " + ", ".join(columns) + " FROM football_players"

# Execute the query
query = container.query(select_statement)
rs = query.fetch(False)

data = rs.fetch_rows()

print(data.head())
```

## **探索的データ分析**

推進システムを構築する前に、データの矛盾点を見つけ、データセットの全体的な視覚化を可能にする探索的データ分析から始めなければなりません。まず、属性にNull値がないかチェックすることから始めます。これは以下のコードで実現されます。

```python
data.isnull().sum()
```

このセルは以下の結果を出力し、**region**属性に**1つの**欠損値があることを示します。

```python
name            0
club            0
age             0
position        0
position_cat    0
market_value    0
page_views      0
fpl_value       0
fpl_sel         0
fpl_points      0
region          1
nationality     0
new_foreign     0
age_cat         0
club_id         0
big_club        0
new_signing     0
dtype: int64
```

欠損値を一掃するには、組み込みメソッド `dropna()` を使うことができます。このメソッドは、古いクリーンでないデータセットに代わって、新しくクリーン化されたデータセットを返します。

これは以下のコードで実現できます。

```python
data = data.dropna()
```

すべての欠損値を置き換えたので、データの可視化に移ることができます。データをグラフ化するための最初のステップは、`corr()` メソッドを使用して、他の選手を予測するために使用できるさまざまな属性を表す相関行列を計算することです。これは、どのデータポイントがプレーヤーを推薦するために使用できるのか、また、データセットに示された属性の観点から、すべてのプレーヤーがどのように測定されるのかを示すので、非常に便利です。

これは以下のコードで実現できます。

```python
sample = data.select_dtypes(include='number')
corr = sample.corr()
mask = np.zeros_like(corr, dtype = np.bool_)
mask[np.triu_indices_from(mask)] = True
plt.figure(figsize=(10,10))
sns.heatmap(corr, mask=mask)
```

このセクションで考えたグラフは、**X**軸と**Y**軸の属性を取り、所定のスケールで相関を測定するヒートマップです。ヒートマップは以下の通りです。

![image][9]

## **レコメンデーションシステム**

このセクションでは、レコメンデーションシステムのモデルを設計し、準備します。その為に、まず標準的なスケーラーを用いてデータポイントを数値に変換することから始めます。次に、レコメンデーションシステムのアルゴリズムとして使用するニアレストネイバーズモデルを実行します。このモデルは、我々の数値データを入力とし、入力に近い特徴を持つ比較可能な選手を見つけるために使用されます。

これは以下のコードで実現できます。

```python
scaled = StandardScaler()
X = scaled.fit_transform(sample)
recommendations = NearestNeighbors(n_neighbors = 5, algorithm='kd_tree')
recommendations.fit(X)
player_index = recommendations.kneighbors(X)[1]
```

モデルを準備したので、与えられた名前に基づいてデータセット中の選手のインデックスを見つけるメソッドを作らなければなりません。これは、レコメンデーションシステムの結果を使用して、推薦された選手の属性を抽出することができるので、非常に便利です。

これは以下のコードで実現できます。

```python
def find_index(x):
    return data[data['name']==x].index.tolist()[0]
```

最後のステップは、選手の情報を抽出するためのモデルを使ったメソッドを作成することです。言い換えれば、すべての選手について、推奨される選手を説明する主要な値を抽出しなければなりません。私たちの例では、主に選手の名前、市場価値、年齢、現在のクラブに焦点を当てています。

これは以下のコードで実現できます。

```python
def recommendation_system(player):
    print("Here are four players who are similar to {}: ".format(player))
    index =  find_index(player)
    
    for i in player_index[index][1:]:
        print("Player Name: {}\nPlayer Market Value: €{}\nPlayer Age: {}\nPlayer Current Club: {}\n".format(
            data.iloc[i]['name'],
            data.iloc[i]['market_value'], 
            data.iloc[i]['age'], 
            data.iloc[i]['club']))
```

## モデル評価

この時点で、モデルを評価する準備が整いました。この例では、選手名を入力し、入力者に匹敵する**4人の**キープレーヤーを推薦するレコメンデーションシステムを実行します。

このコードは次のようにして実現できます。

```python
recommendation_system('Petr Cech')
```

我々のモードの結果は以下の通りです。

```python
Here are four players who are similar to Petr Cech: 
Player Name: Willy Caballero
Player Market Value: €1.5
Player Age: 35
Player Current Club: Chelsea

Player Name: Nacho Monreal
Player Market Value: €13.0
Player Age: 31
Player Current Club: Arsenal

Player Name: Laurent Koscielny
Player Market Value: €22.0
Player Age: 31
Player Current Club: Arsenal

Player Name: Artur Boruc
Player Market Value: €1.0
Player Age: 37
Player Current Club: Bournemouth
```

見て分かるように、レコメンデーションシステムは入力選手と非常に近い5人の選手を高い精度で予測することができました。これは、私たちのモデルがすぐにでも導入可能であり、現在の選手に基づいて将来の才能を予測するために使用できることを証明しています。

## **結論**

ビジネスにおいてレコメンデーションシステムを使って見込み客リストを作成することは、競争上の優位性になりますし、どのチームのマネージャーも考慮すべきです。この記事では、イングランド・プレミアリーグの選手を使ったレコメンデーションモデルをステップ・バイ・ステップで作成するプロセスを取り上げました。GridDBは、我々のデータセットのデータベースストレージとして、この記事で広範囲に使用されました。このデータベースは、学習済みデータを保存し、レコメンデーションシステムを呼び出して、仲間に基づいてサッカー選手を推薦するために使用されます。

 [1]: https://docs.griddb.net/ja/latest/gettingstarted/python/#インストール
 [2]: https://www.python.org/downloads/
 [3]: https://jupyter.org/install
 [4]: https://github.com/griddb/c_client
 [5]: https://github.com/griddb/python_client
 [6]: https://pypi.org/project/griddb-python/
 [7]: https://www.kaggle.com/datasets/mauryashubham/english-premier-league-players-dataset
 [8]: https://github.com/SimoCs/Soccer-Players-Recommendation-System/assets/32298957/68333831-8e5a-4589-afc3-c4d2ea16c733
 [9]: https://github.com/SimoCs/Soccer-Players-Recommendation-System/assets/32298957/c863ddd6-7b06-47cd-b238-edd48aa10dcb