FIFA20 對技能相近的球員分組(3):DBSCAN

瞭解 DBSCAN

  • 基於密度的噪聲應用空間聚類。
  • 基於密度的聚類定位高密度區域,這些高密度區域被低密度區域彼此分開。
  • 密度:指定半徑內的點數(又名 Eps 或 ε)。

點數

  • 核心點 :如果一個點在 Eps 中有超過指定數量的點(MinPts)。、
  • 邊界點 :它在 EPS 中少於 MinPts,但在覈心點附近。
  • 噪音點(離羣值) :不是核心點或邊界點的任何點。

核心點、邊界點、離羣值示例。

集羣如何形成?

  1. 選擇一個點 P。
  2. 從 p.w.t. eps 和 MinPts 中檢索密度可達的所有點。
  • 如果 p 是核心點,則形成一個聚類。
  • 如果 p 是邊界點,則從 p 沒有密度可達的點,並且 DBSCAN 將訪問數據庫的下一個點。
  1. 繼續執行該過程,直至所有點都已處理完畢。
  2. 結果與點的處理順序無關。

ε-鄰域概念

  • 從對象到 ε 半徑內的對象。
  • 和新對象:一個對象的 ε-鄰域 至少包含 MinPts 個 對象。

p 爲和新對象

可達性

  • 直接密度可達 :如果 q 在 p 的 ε-鄰域內,且 p 爲核心點,則點 q 是從 p 直接密度可達的。

  • 密度可達 :如果點 p 在點 q 的 ε 距離內,且點 q 在其鄰近點的可達距離 ε 內有足夠數量的點,則稱點 p 是從點 q 密度可達。

連接性

  • 密度連接性 :如果存在點 r,使得點 p 和點 q 可以從 r 的 w.r.t. ε 和 MinPts 密度可達,則點 p 密度連接到點 q。

q 通過 r 密度連接到 p

優缺點及應用

優點 缺點 應用
對離羣值檢測的健壯性 對 eps 和 MinPts 敏感 衛星圖像
最適合分離高密度的聚類與低密度的聚類 若數據集過於稀疏,則不合適 異常檢測

使用 DBSCAN 對 FIFA 20 球員進行分組

數據清理/預處理(第一部分和第二部分的代碼)

import pandas as pd
import numpy as np
df = pd.read_csv("/content/players_20.csv")
df = df[['short_name','age', 'height_cm', 'weight_kg', 'overall', 'potential','value_eur', 'wage_eur', 'international_reputation', 'weak_foot','skill_moves', 'release_clause_eur', 'team_jersey_number','contract_valid_until', 'nation_jersey_number', 'pace', 'shooting','passing', 'dribbling', 'defending', 'physic', 'gk_diving','gk_handling', 'gk_kicking', 'gk_reflexes', 'gk_speed','gk_positioning', 'attacking_crossing','attacking_finishing','attacking_heading_accuracy', 'attacking_short_passing','attacking_volleys', 'skill_dribbling', 'skill_curve','skill_fk_accuracy', 'skill_long_passing','skill_ball_control','movement_acceleration', 'movement_sprint_speed', 'movement_agility','movement_reactions', 'movement_balance', 'power_shot_power','power_jumping', 'power_stamina', 'power_strength', 'power_long_shots','mentality_aggression', 'mentality_interceptions','mentality_positioning', 'mentality_vision', 'mentality_penalties','mentality_composure', 'defending_marking', 'defending_standing_tackle','defending_sliding_tackle', 'goalkeeping_diving','goalkeeping_handling', 'goalkeeping_kicking','goalkeeping_positioning', 'goalkeeping_reflexes']]
df = df[df.overall > 86] # extracting players with overall above 86
df = df.fillna(df.mean())
names = df.short_name.tolist() # saving names for later
df = df.drop(['short_name'], axis = 1) # drop the short_name column
df.head()

標準化數據

from sklearn import preprocessing
x = df.values # numpy array
scaler = preprocessing.MinMaxScaler()
x_scaled = scaler.fit_transform(x)
X_norm = pd.DataFrame(x_scaled)

使用 PCA 將 60 列減少到 2 列

from sklearn.decomposition import PCA
pca = PCA(n_components = 2) # 2D PCA for the plot
reduced = pd.DataFrame(pca.fit_transform(X_norm))

應用 DBSCAN

from sklearn.cluster import DBSCAN
# train the model using DBSCAN
db = DBSCAN(eps=1, min_samples=5)
# the prediction for dbscan clusters
db_clusters = db.fit_predict(reduced)

通過添加球員名字和他們的聚類來創建新的數據幀

reduced['cluster'] = db_clusters
reduced['name'] = names
reduced.columns = ['x', 'y', 'cluster', 'name']
reduced.head()

繪製 DBSCAN

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.set(style="white")
ax = sns.lmplot(x="x", y="y", hue='cluster', data = reduced, legend=False,fit_reg=False, size = 10, scatter_kws={"s": 250})
texts = []
for x, y, s in zip(reduced.x, reduced.y, reduced.name):
    texts.append(plt.text(x, y, s))

ax.set(ylim=(-2, 2))
plt.tick_params(labelsize=15)
plt.xlabel("PC 1", fontsize = 20)
plt.ylabel("PC 2", fontsize = 20)
plt.show()

DBSCAN,Eps=1,MinPts=5

  • 聚類形成爲守門員和其他球員
  • 不是很準確

尋找最佳 ε

  • 通過計算每個點到最近的 n 個點的距離,對結果進行排序和繪製,找出最佳 ε。
from sklearn.neighbors import NearestNeighbors
# calculate the distance from each point to its closest neighbor
nn = NearestNeighbors(n_neighbors = 2)
# fit the nearest neighbor
nbrs = nn.fit(reduced)
# returns two arrays - distance to the closest n_neighbors points and index for each point
distances, indices = nbrs.kneighbors(reduced)
# sort the distance and plot it
distances = np.sort(distances, axis=0)
distances = distances[:,1]
plt.plot(distances)

尋找最佳 ε

使用新的 Eps 再次應用 DBSCAN

from sklearn.cluster import DBSCAN
# train the model using DBSCAN
db= DBSCAN(eps=0.3, min_samples=4)
# prediction for dbscan clusters
db_clusters = db.fit_predict(reduced)
reduced['cluster'] = db_clusters
reduced['name'] = names
reduced.columns = ['x', 'y', 'cluster', 'name']
reduced.head()

以新的 Eps=0.3 和 MinPts=4 再次繪製

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.set(style="white")
ax = sns.lmplot(x="x", y="y", hue='cluster', data = reduced, legend=False,fit_reg=False, size = 9, scatter_kws={"s": 250})
texts = []
for x, y, s in zip(reduced.x, reduced.y, reduced.name):
    texts.append(plt.text(x, y, s))

ax.set(ylim=(-2, 2))
plt.tick_params(labelsize=10)
plt.xlabel("PC 1", fontsize = 20)
plt.ylabel("PC 2", fontsize = 20)
plt.show()

Eps=0.3,MinPts=4 的 DBSCAN 圖

結論

使用 Eps=0.3 和 MinPts=4 的 DBSCAN 在分組和檢測離羣值方面做得更好!

感謝閱讀本文,希望對您有所幫助!

GitHub Repo: https://github.com/importdata/Clustering-FIFA-20-Players

作者介紹

Jaemin Lee,專攻數據分析與數據科學,數據科學應屆畢業生。

原文鏈接

https://towardsdatascience.com/grouping-soccer-players-with-similar-skillsets-in-fifa-20-part-3-dbscan-b23389a08cc7

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章