머신러닝 - 결정 트리(Decision Tree)를 기반으로 운동 경기 결과 예측하기
- 지도 학습이란 ?
- 개발 환경 설정 : skikit-learn과 pandas
- 분류 문제와 결정 트리
- 교차 검증
- NBA 경기 데이터 수집 및 전처리
- 2015 ~ 16년 NBA 경기의 데이터를 수집하자.
import os
import pandas
home_folder = os.path.expanduser(os.getcwd()) # 현재 디렉토리를 home_folder로 지정
data_folder = os.path.join(home_folder,"resources") # [1]
'''
[1]
home_folder로 부터 타고 타고 들어간다.
os.path.join(home_folder,"resources") ==> home_folder/resources
os.path.join(home_folder,"resources","test") ==> home_folder/resources/test
'''
data_files=["nba_2015_10.csv", "nba_2015_11.csv", "nba_2015_12.csv",
"nba_2016_01.csv", "nba_2016_02.csv", "nba_2016_03.csv",
"nba_2016_04.csv", "nba_2016_05.csv", "nba_2016_06.csv"]
cvs_objs = []
for f in data_files:
month_data = os.path.join(data_foler, f)
cvs_objs.append(pandas.read_csv(month_data))
season_result = pandas.concat(cvs_objs, ignore_index=True)
# 데이터 컬럼의 제목을 지정
season_result.columns = ["Date", "StartTime", "VisitorTeam", "VisitorPts",
"HomeTeam", "HomePts", "ScoreType", "Overtime", "Notes"]
print(season_result[-2:]) # 끝에서 2번째 부터 마지막까지 출력
Date StartTime VisitorTeam VisitorPts \
1309 Sun Jun 14 2015 8:00 pm Cleveland Cavaliers 91
1310 Tue Jun 16 2015 9:00 pm Golden State Warriors 105
HomeTeam HomePts ScoreType Overtime Notes
1309 Golden State Warriors 104 Box Score NaN NaN
1310 Cleveland Cavaliers 97 Box Score NaN NaN
pandas의 read_csv() 메서드를 이용하면 CSV 형태의 파일로부터
2차원 테이블 형태의 데이터 프레임 객체를 얻을 수 있다.
또한 월별로 분리된 데이터 프레임 객체를 concat() 메서드를 이용해
하나의 큰 데이터 프레임 객체로 합칠 수 있다.
이 때 ignore_index의 인자를 True로 설정하면
새롭게 생성되는 데이터 프레임에서는 월별 데이터의 인덱스를 사용하는 대신에
새롭게 카운팅하게 된다.
season_result["HomeWin"] = season_result["HomePts"] > season_result["VisitorPts"]
print(season_result[-2:])
Date StartTime VisitorTeam VisitorPts \
1309 Sun Jun 14 2015 8:00 pm Cleveland Cavaliers 91
1310 Tue Jun 16 2015 9:00 pm Golden State Warriors 105
HomeTeam HomePts ScoreType Overtime Notes HomeWin
1309 Golden State Warriors 104 Box Score NaN NaN True
1310 Cleveland Cavaliers 97 Box Score NaN NaN False
season_result에 ‘HomeWin’ 컬럼을 추가해
홈팀의 승패 여부를 확인해 볼 수 있다.
또한 스포츠 경기에서 상위권의 팀은
핵심 선수의 부상/은퇴/이적과 같은 특별한 이변이 없는 한
상위권을 지속해서 유지하는 경향이 있다.
2014~15 시즌의 순위 역시 결정 트리의 특성 값으로 활용할 수 있다.
standing_file = os.path.join(data_folder, "nba_2014_2015_standing.csv")
# standing_file에 0번째 줄은 불필요한 데이터이므로 skip
standing_result = pandas.read_csv(standing_file, skiprows=[0])
선수 개개인의 능력 또하 게임의 승패에 큰 영향을 끼친다.
농구 경기에서 분당 생산적인 활동을 얼마나 하는지 나타내는 지수로
PER(Player Efficiency Rating)이 있으며,
2015~16년 시즌 PER 수치 또한 결정 트리의 특성 값으로 활용할 수 있다.
player_file = os.path.join(data_folder, "nba_2016_player_stat.csv")
player_result = pandas.read_csv(player_file)
이제 NBA 리그의 모든 선수 데이터를 순회하면서
각 선수의 팀과 PER 값을 추출한 다음
team_per딕셔너리에 팀의 이름은 키로, 선수 개개인의 PER 값은 리스트 형태로 추가한다.
team_per = {}
for key, value in team_name.items():
team_per[value] = []
for idx, row in player_result.iterrows():
player = row["PLAYER"]
per = row["PER"]
team_list = player.split(',')[1].strip(' ').split("/")
for team in team_list:
team_per[team_name[team]].append(per)
이렇게 저장된 팀별 PER 지수가 정말 의미가 있는지 확인해보자.
import numpy
print("Golden State Warriors: Sum of PER: {0:.2f} / Mean of PER: {1:.2f}"
.format(numpy.sum(team_per["Golden State Warriors"]), numpy.mean(team_per["Golden State Warriors"])))
print("Philadelphia 76ers: Sum of PER: {0:.2f} / Mean of PER: {1:.2f}"
.format(numpy.sum(team_per["Philadelphia 76ers"]), numpy.mean(team_per["Philadelphia 76ers"])))
Golden State Warriors: Sum of PER: 192.37 / Mean of PER: 16.03
Philadelphia 76ers: Sum of PER: 165.17 / Mean of PER: 13.76