Bisakah kecerdasan buatan meninggalkan bandar tanpa bekerja?

"Kemenangan kecerdasan buatan atas pakar sepak bola" - ini bisa menjadi judul artikel ini tentang hasil kompetisi sepakbola. Bisa, tetapi, sayangnya, tidak.

Selama Piala Dunia, di perusahaan kami " NORBIT " mengadakan kompetisi untuk pertandingan ramalan sepakbola terbaik. Saya terlalu berpengalaman dalam sepakbola untuk mengklaim apa pun, tetapi keinginan untuk ikut serta dalam kompetisi masih menang karena kemalasan saya. Di bawah potongan - sebuah cerita tentang bagaimana, berkat pembelajaran mesin, saya berhasil mencapai hasil yang baik di antara para ahli di tim sepak bola. Benar, saya gagal mencapai jackpot, tetapi saya menemukan dunia baru yang menarik dari Ilmu Data.


Saya mulai dengan hipotesis bahwa, di samping keterampilan individu pemain tim nasional, masih ada banyak faktor yang tak terukur, tetapi penting - semangat tim + kerja tim (misalnya, tim dalam permainan dengan lawan yang lebih kuat, tetapi dalam pertandingan uji dan di lapangan mereka lebih sering menang). Tugas ini tidak begitu sederhana untuk seseorang, tetapi cukup dimengerti untuk pembelajaran mesin.

Saya pernah punya sedikit pengalaman bekerja dengan ML (dengan perpustakaan BrainJS), tetapi kali ini saya memutuskan untuk memeriksa pernyataan bahwa Python jauh lebih cocok untuk tugas-tugas seperti itu.

Saya mulai perkenalan saya dengan Python dengan kursus yang sangat baik tentang Coursera , dan saya belajar dasar-dasar pembelajaran mesin dari serangkaian artikel dari Open Data Science on HabrΓ© .

Cukup cepat saya menemukan Dataset yang sangat baik dengan sejarah semua pertandingan tim internasional sejak awal abad ke-20. Setelah mengimpor ke dalam kerangka data Pandas:


Secara total, database berisi informasi tentang 39 ribu permainan tim internasional.

Pandas membuatnya sangat nyaman untuk menganalisis data, misalnya, pertandingan paling produktif adalah antara Australia dan Samoa Amerika pada tahun 2001, yang berakhir dengan skor 31: 0 .




Sekarang Anda perlu menambahkan penilaian objektif tingkat tim pada tahun pertandingan. Penilaian ini ditangani oleh FIFA.



Namun, sayangnya, peringkat FIFA baru dilakukan sejak 1992. Dan, dilihat dari jadwal, peringkat tim sangat rentan terhadap perubahan, dan saya benar-benar tidak ingin rata-rata posisi tim di peringkat dunia hingga tahun ini.

UEFA menyimpan statistiknya dari zaman yang lebih kuno, tetapi saya tidak dapat menemukan dataset yang sudah siap, jadi situs ini datang untuk menyelamatkan. Di bawah Node.js ada Cheerio yang kuat dan nyaman untuk tugas-tugas seperti itu, tetapi di bawah Python semuanya ternyata tidak kurang sederhana (maafkan saya administrator situs ini).

Peringkat kerokan web
from requests import get from requests.exceptions import RequestException from contextlib import closing from bs4 import BeautifulSoup def query_url(url):    try: with closing(get(url, stream=True)) as resp:        if is_good_response(resp):        return resp.content else:         return None   except RequestException as e: log_error('Error during requests to {0} : {1}'.format(url, str(e))) return None def is_good_response(resp):    content_type = resp.headers['Content-Type'].lower()    return (resp.status_code == 200        and content_type is not None        and content_type.find('html') > -1) def log_error(e):    print(e) def parse_ranks(raw_html, year):    html = BeautifulSoup(raw_html, 'html.parser')    ranks = []    for tr in html.select('tr'):        tds = tr.select("td")    if len(tds) == 10:        rank = (year, tds[2].text, tds[7].text)        ranks.append(rank)    return ranks   def get_url(year):    if year in range(1960, 1999): method = 1    if year in range(1999, 2004): method = 2    if year in range(2004, 2009): method = 3    if year in range(2009, 2018): method = 4    if year in range(2018, 2019): method = 5    return f"https://kassiesa.home.xs4all.nl/bert/uefa/data/method{method}/crank{year}.html" ranks = [] for year in range(1960, 2019):    url = get_url(year)    print(url)    raw_html = query_url(url)    rank = parse_ranks(raw_html, year)    ranks += rank   with open('team_ranks.csv', 'w') as f:    writer = csv.writer(f , lineterminator='\n')    writer.writerow(['year', 'country', 'rank'])    for rank in ranks:    writer.writerow(rank) 


Fluktuasi peringkat setelah menambahkan peringkat UEFA (dan sedikit revisi nama-nama negara sesuai dengan hasil castling geopolitik):


Tetapi bahkan di sini, satu tong tar tidak dibagikan - UEFA hanya mengurutkan tim-tim Eropa (Anda terkadang perlu memikirkan apa yang disembunyikan di bawah singkatan umum sebelum menggunakannya). Untungnya, babak playoff telah berkembang hampir "Eropa".

Tetap sedikit lebih nyaman untuk membagi hasil menjadi permainan yang terpisah dan menambahkan peringkat ke tabel.

Bagian yang paling menarik adalah pelatihan model. Google segera menyarankan opsi paling sederhana dan tercepat - ini adalah MLPClassifier dari Python library - Sklearn. Mari kita coba latih model menggunakan contoh Swedia.

 from sklearn.neural_network import MLPClassifier games = pd.read_csv('games.csv') #    SwedenGames = games[(games.teamTitle == 'Sweden')] #   y = SwedenGames['score'] y = y.astype('int') #   X = SwedenGames.drop(['score', 'teamTitle', 'againstTitle'], axis=1) #       X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25) mlp = MLPClassifier() mlp.fit(X_train, y_train); predictions = mlp.predict(X_test) print('Accuracy: {:.2}'.format(   accuracy_score(y_test, mlp.predict(X_test)) )) 

Akurasi: 0,62

Tidak jauh lebih akurat daripada melempar koin, tapi mungkin sudah lebih baik dari perkiraan "ahli" potensial saya. Akan masuk akal untuk mencoba memperkaya data, bermain dengan hyperparameters, tapi saya memutuskan untuk pergi ke arah lain dan mencoba meningkatkan Yandex gradien perpustakaan Boost . Di satu sisi, ini lebih patriotik, di sisi lain, mereka menjanjikan karya berkualitas dengan atribut kategoris, yang dikonfirmasi oleh berbagai perbandingan .

Mengambil pengaturan dari contoh :

 #     categorical_features_indices = [1, 2, 4] train_pool = Pool(X_train,  y_train, cat_features=categorical_features_indices) validate_pool = Pool(X_test, y_test, cat_features=categorical_features_indices) #      ,      GridSearchCV.   best_params = {   'iterations': 500,   'depth': 10,   'learning_rate': 0.1,   'l2_leaf_reg': 1,   'eval_metric': 'Accuracy',   'random_seed': 42,   'logging_level': 'Silent',   'use_best_model': True } cb_model = CatBoostClassifier(**best_params) cb_model.fit(train_pool, eval_set=validate_pool) print('Accuracy: {:.2}'.format(   accuracy_score(y_test, cb_model.predict(X_test)) )) 

Akurasi: 0,73

Sudah lebih baik, coba dalam praktek.

 def get_prediction(country, against):   y = SwdenGames['score']   y = y.astype('int')   X = SwdenGames.drop(['score', 'againstTitle'], axis=1)   train_pool = Pool(X, y, cat_features=[1, 2, 4])   query = [ get_team_rank(country, 2018), 0,   1 if country == 'Russia' else 0,   get_team_rank(against, 2018),   against]   return cb_model.predict_proba([query])[0] team_1 = 'Belgium' team_2 = 'France' result = get_prediction(team_1, team_2) if result[0] > result[1]:   print(f" {team_1}    {team_2}   {result[0]*100:.1f}%") else: print(f" {team_1}   {team_2}   {result[1]*100:.1f}%") 


Hasil Prediksi untuk Final β€œTim Crotia Kalah dari Tim Prancis dengan Kemungkinan 93,7%”

Meskipun kali ini saya tidak memenangkan kontes NORBIT , saya sangat berharap artikel ini akan mengurangi tingkat sihir bagi seseorang dalam penggunaan praktis pembelajaran mesin, atau bahkan mungkin memotivasi saya untuk melakukan eksperimen sendiri.

Source: https://habr.com/ru/post/id427273/


All Articles