AI

테트리오 랭크 예측

수박쓰123 2024. 6. 12. 11:43

테트리오 데이터를 분석해서 랭크를 예측하는 코드를 만들어보자


 

우선 테트리오 사이트의 데이터들을 받아와 봤다

 

위의 사진은 받아온 데이터의 일부인데 여기서 내가 쓸 데이터는

rank, apm, pps, vs, 40l-sprint, blitz 다.

 

간단한 설명을 해주자면

  • rank; 랭겜을 돌려서 랭크를 받을 수 있다
  • apm(attack per minute): 분당 공격 횟수
  • pps(pieces per second): 초당 블럭 쌓는 수
  • vs(versus score): 대결 점수
  • 40l-sprint: 테트리오 사이트의 모드 중 하나로 40줄을 제거하면 되는 모드
  • blitz: 테트리오 사이트의 모드 중 하나로 제한시간 안에 최대한 많은 줄을 제거하는 모드

이렇게 5가지를 입력했을 때 랭크를 예측시켜 주는 코드를 짤 것이다.

 


1단계. 데이터 전처리

테트리오 모든 유저의 데이터를 불러왔다보니 어떤 유저는 랭겜을 돌리지 않았고, 어떤 유저는 blitz를 플레이하지 않는 등 데이터가 군데군데 비어있는게 보이니 하나라도 데이터가 비어있는 행은 제거하도록 하자

# 1. 데이터 전처리
# 필요한 컬럼만 선택합니다.
features = ['apm', 'pps', 'vs', '40l_sprint', 'blitz']
target = 'rank'

# apm, pps, vs, 40l_sprint, blitz 중 하나라도 비어있는 행 제거
tetrio_data_clean = tetrio_data.dropna(subset=features)

 


2단계. 시각화

각 수치가 랭크와 어떤 상관관계가 있는지 확인해보자

# blitz 열을 수치형으로 변환
tetrio_data_clean['blitz'] = pd.to_numeric(tetrio_data_clean['blitz'], errors='coerce')

# 변환 후 NaN 값을 가진 행 제거
tetrio_data_clean = tetrio_data_clean.dropna(subset=['blitz', '40l_sprint', 'apm', 'pps', 'vs'])

# blitz 열의 값 확인
print(tetrio_data_clean['blitz'].describe())

# 40l_sprint 열의 값 확인
print(tetrio_data_clean['40l_sprint'].describe())

# blitz 열의 이상치 제거 (5000 이하의 값 제거)
tetrio_data_clean = tetrio_data_clean[tetrio_data_clean['blitz'] > 10000]

# 40l_sprint 열의 이상치 제거 (400 이상의 값 제거)
tetrio_data_clean = tetrio_data_clean[tetrio_data_clean['40l_sprint'] < 250]

# 바이올린 플롯으로 그래프 그리기
plt.figure(figsize=(15, 10))

# apm vs rank
plt.subplot(3, 2, 1)
sns.violinplot(x='rank', y='apm', data=tetrio_data_clean, palette='Set2')
plt.title('APM vs Rank')
plt.xticks(rotation=90)

# pps vs rank
plt.subplot(3, 2, 2)
sns.violinplot(x='rank', y='pps', data=tetrio_data_clean, palette='Set2')
plt.title('PPS vs Rank')
plt.xticks(rotation=90)

# vs vs rank
plt.subplot(3, 2, 3)
sns.violinplot(x='rank', y='vs', data=tetrio_data_clean, palette='Set2')
plt.title('VS vs Rank')
plt.xticks(rotation=90)

# 40l_sprint vs rank
plt.subplot(3, 2, 4)
sns.violinplot(x='rank', y='40l_sprint', data=tetrio_data_clean, palette='Set2')
plt.title('40L Sprint vs Rank')
plt.xticks(rotation=90)

# blitz vs rank
plt.subplot(3, 2, 5)
sns.violinplot(x='rank', y='blitz', data=tetrio_data_clean, palette='Set2')
plt.title('Blitz vs Rank')
plt.xticks(rotation=90)

plt.tight_layout()
plt.show()

 


3. 데이터 분석

이제 이 데이터를 분석해서 예시를 입력을 했을 때 랭크를 예측할 수 있도록 해보자

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

# 필요 없는 열 제거
tetrio_data_clean = tetrio_data_clean.dropna(subset=['rank'])

# 특성과 레이블 정의
X = tetrio_data_clean[['apm', 'pps', 'vs', '40l_sprint', 'blitz']]
y = tetrio_data_clean['rank']

# 학습 데이터와 테스트 데이터로 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 모델 학습
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# 예측
y_pred = model.predict(X_test)

# 새로운 값 예측 함수
def predict_rank(apm, pps, vs, sprint, blitz):
    data = pd.DataFrame([[apm, pps, vs, sprint, blitz]], columns=['apm', 'pps', 'vs', '40l_sprint', 'blitz'])
    prediction = model.predict(data)
    return prediction[0]

# 사용자 입력 받기
def get_user_input():
    try:
        apm = float(input("Enter APM: "))
        pps = float(input("Enter PPS: "))
        vs = float(input("Enter VS: "))
        sprint = float(input("Enter 40L Sprint time: "))
        blitz = float(input("Enter Blitz score: "))
        return apm, pps, vs, sprint, blitz
    except ValueError:
        print("Invalid input. Please enter numeric values.")
        return get_user_input()

# 예측 테스트
user_apm, user_pps, user_vs, user_sprint, user_blitz = get_user_input()
predicted_rank = predict_rank(user_apm, user_pps, user_vs, user_sprint, user_blitz)
print(f'Predicted Rank: {predicted_rank}')

4. 문제

이제 테트리오 사이트에서 내 값을 테스트 겸 입력해보려 했는데

큰일났다.

데이터셋에 이미 내 계정 정보가 들어가있었다.

 

그래서 급하게 새로운 계정을 팠다.

 

 

근데 다시 생각해보니깐 이게 aps, pps, vs는 랭겜을 돌려야 쌓이니깐 예측이 쓸모가 없다. 그러니 40l-sprint와 blitz만을 사용해서 랭크를 예측하도록 바꿔보자

 

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from google.colab import files

file_name = list(uploaded.keys())[0]

# 데이터 로드
tetrio_data = pd.read_csv(io.BytesIO(uploaded[file_name]))

# 필요한 컬럼만 선택합니다.
features = ['40l_sprint', 'blitz']
target = 'rank'

# 40l_sprint, blitz, rank 중 하나라도 비어있는 행 제거
tetrio_data_clean = tetrio_data.dropna(subset=features + [target])

# blitz 열을 수치형으로 변환
tetrio_data_clean['blitz'] = pd.to_numeric(tetrio_data_clean['blitz'], errors='coerce')

# 변환 후 NaN 값을 가진 행 제거
tetrio_data_clean = tetrio_data_clean.dropna(subset=['blitz', '40l_sprint'])

# 특성과 레이블 정의
X = tetrio_data_clean[['40l_sprint', 'blitz']]
y = tetrio_data_clean['rank']

# 학습 데이터와 테스트 데이터로 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 모델 학습
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# 새로운 값 예측 함수
def predict_rank(sprint, blitz):
    data = pd.DataFrame([[sprint, blitz]], columns=['40l_sprint', 'blitz'])
    prediction = model.predict(data)
    return prediction[0]

# 사용자 입력 받기
def get_user_input():
    try:
        sprint = float(input("Enter 40L Sprint time: "))
        blitz = float(input("Enter Blitz score: "))
        return sprint, blitz
    except ValueError:
        print("Invalid input. Please enter numeric values.")
        return get_user_input()

# 예측 테스트
user_sprint, user_blitz = get_user_input()
predicted_rank = predict_rank(user_sprint, user_blitz)
print(f'Predicted Rank: {predicted_rank}')

 


5. 테스트

예측이 잘 된다~