هل يمكن للذكاء الاصطناعي ترك مكاتب المراهنات بدون عمل؟

"انتصار الذكاء الاصطناعي على خبراء كرة القدم" - قد يكون هذا عنوان هذا المقال حول نتائج مسابقة كرة القدم. يمكن ، ولكن للأسف ، لم يفعل ذلك.

خلال كأس العالم ، عقدت شركة NORBIT مسابقة لأفضل المباريات المتوقعة لكرة القدم. أنا ضحية سطحية للغاية في كرة القدم للمطالبة بأي شيء ، لكن الرغبة في المشاركة في المسابقة لا تزال تفوز على كسلتي. تحت القصة - قصة عن كيف تمكنت بفضل التعلم الآلي من تحقيق نتائج جيدة بين الخبراء في فرق كرة القدم. صحيح ، لقد فشلت في الفوز بالجائزة الكبرى ، لكنني اكتشفت عالمًا جديدًا رائعًا لعلوم البيانات.


لقد بدأت بفرضية أنه بالإضافة إلى المهارات الفردية للاعبي المنتخب الوطني ، لا تزال هناك عوامل لا حصر لها ، ولكنها عوامل مهمة - روح الفريق + العمل الجماعي (على سبيل المثال ، فريق في لعبة مع خصم أقوى ، ولكن في مباراة الاختبار وفي ميدانهم في كثير من الأحيان يفوز). إن المهمة ليست بهذه السهولة بالنسبة لشخص ما ، ولكنها مفهومة تمامًا لتعلم الآلة.

كانت لدي تجربة صغيرة مع ML (مع مكتبة BrainJS) ذات مرة ، ولكن هذه المرة قررت التحقق من البيان الذي مفاده أن Python أكثر ملاءمة لمثل هذه المهام.

لقد بدأت مقدمتي إلى Python بدورة ممتازة عن Coursera ، وتعلمت أساسيات التعلم الآلي من سلسلة من المقالات من Open Data Science على Habré .

سرعان ما وجدت مجموعة بيانات ممتازة مع تاريخ جميع مباريات الفرق الدولية منذ بداية القرن العشرين. بعد الاستيراد إلى Pandas dataframe:


في المجموع ، تحتوي قاعدة البيانات على معلومات عن 39 ألف مباراة لفرق دولية.

تجعل Pandas من الملائم للغاية تحليل البيانات ، على سبيل المثال ، كانت المباراة الأكثر إنتاجية بين أستراليا وساموا الأمريكية في عام 2001 ، والتي انتهت بنتيجة 31: 0 .




تحتاج الآن إلى إضافة تقييم موضوعي لمستوى الفريق في سنة المباراة. يتم التعامل مع هذه التقييمات من قبل FIFA.



ولكن للأسف ، تم إجراء تصنيف FIFA منذ عام 1992 فقط. وبحسب الجدول الزمني ، فإن تقييمات الفريق عرضة للتغيرات بشكل كبير ، ولا أود حقاً أن أحسب متوسط ​​مراكز الفرق في التصنيف العالمي حتى هذا العام.

يحتفظ الاتحاد الأوروبي لكرة القدم (UEFA) بإحصاءاته من العصور القديمة ، لكن لم أتمكن من العثور على مجموعة بيانات جاهزة ، لذلك جاء هذا الموقع إلى الإنقاذ. تحت Node.js هناك Cheerio قوي ومريح لمثل هذه المهام ، ولكن تحت Python تبين أن كل شيء ليس أقل بساطة (سامحني مدير هذا الموقع).

ترتيب تجريف الويب
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) 


التقلبات في التصنيف بعد إضافة تصنيف الاتحاد الأوروبي (ومراجعة صغيرة لأسماء الدول حسب نتائج التبييت الجيوسياسي):


ولكن حتى هذا لم يكن بدون برميل من القطران - يصنف الاتحاد الأوروبي فقط الفرق الأوروبية (في بعض الأحيان تحتاج إلى التفكير في ما هو مخفي تحت الاختصارات الشائعة قبل استخدامها). لحسن الحظ ، تطورت التصفيات "الأوروبية" تقريبًا.

يبقى أكثر ملاءمة لتقسيم النتائج إلى ألعاب منفصلة وإضافة تقييمات إلى الطاولة.

الجزء الأكثر إثارة للاهتمام هو تدريب النموذج. اقترح Google على الفور الخيار الأبسط والأسرع - هذا هو MLPClassifier من مكتبة Python - Sklearn. دعونا نحاول تدريب نموذج باستخدام مثال السويد.

 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)) )) 

الدقة: 0.62

ليس أكثر دقة من رمي العملة ، ولكن ربما يكون أفضل بالفعل من توقعاتي "الخبيرة" المحتملة. سيكون من المعقول محاولة إثراء البيانات ، واللعب بمعلمات مفرطة ، لكنني قررت الذهاب في الاتجاه الآخر وتجربة مكتبة كاتربوست Yandex التدرجية . من ناحية ، هذا أكثر وطنية ، من ناحية أخرى ، يعدون بعمل جيد مع سمات فئوية ، وهو ما تؤكده العديد من المقارنات .

أخذت الإعدادات من المثال :

 #     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)) )) 

الدقة: 0.73

أفضل بالفعل ، حاول في الممارسة.

 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}%") 


نتائج التنبؤات النهائية لـ "فريق Crotia يخسر أمام منتخب فرنسا باحتمال 93.7٪"

على الرغم من أنني لم أفز هذه المرة في مسابقة NORBIT ، آمل حقًا أن تقلل هذه المقالة مستوى السحر لشخص ما في الاستخدام العملي للتعلم الآلي ، أو ربما يحفزني على القيام بتجاربي الخاصة.

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


All Articles