Predicting NBA players positions using Keras

In this notebook we will build a neural net to predict the positions of NBA players using the Keras library.


In [654]:
%load_ext autoreload
%autoreload 2


The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload

In [655]:
import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer, StandardScaler

from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout

 Data preparation

We will use the Kaggle dataset "NBA Players stats since 1950", with stats for all players since 1950. We will take special interest in how the pass of time affects to the position of each player, and the definition of the positions themselves (a Small Forward, for example, was absolutely different in the 60's to what it is now)


In [656]:
stats = pd.read_csv(r'data/Seasons_Stats.csv', index_col=0)

The file Seasons_Stats.csv contains the statics of all players since 1950. First, we drop a couple of blank columns, and the "Tm" column, that contains the team.


In [830]:
stats = pd.read_csv(r'data/Seasons_Stats.csv', index_col=0)
stats_clean = stats.drop(['blanl', 'blank2', 'Tm'], axis=1)

In [831]:
stats_clean.head()


Out[831]:
Year Player Pos Age G GS MP PER TS% 3PAr ... FT% ORB DRB TRB AST STL BLK TOV PF PTS
0 1950.0 Curly Armstrong G-F 31.0 63.0 NaN NaN NaN 0.368 NaN ... 0.705 NaN NaN NaN 176.0 NaN NaN NaN 217.0 458.0
1 1950.0 Cliff Barker SG 29.0 49.0 NaN NaN NaN 0.435 NaN ... 0.708 NaN NaN NaN 109.0 NaN NaN NaN 99.0 279.0
2 1950.0 Leo Barnhorst SF 25.0 67.0 NaN NaN NaN 0.394 NaN ... 0.698 NaN NaN NaN 140.0 NaN NaN NaN 192.0 438.0
3 1950.0 Ed Bartels F 24.0 15.0 NaN NaN NaN 0.312 NaN ... 0.559 NaN NaN NaN 20.0 NaN NaN NaN 29.0 63.0
4 1950.0 Ed Bartels F 24.0 13.0 NaN NaN NaN 0.308 NaN ... 0.548 NaN NaN NaN 20.0 NaN NaN NaN 27.0 59.0

5 rows × 49 columns

A second file, players.csv, contains static information for each player, as height, weight, etc.


In [835]:
players = pd.read_csv(r'data/players.csv', index_col=0)
players.head(10)


Out[835]:
Player height weight collage born birth_city birth_state
0 Curly Armstrong 180.0 77.0 Indiana University 1918.0 NaN NaN
1 Cliff Barker 188.0 83.0 University of Kentucky 1921.0 Yorktown Indiana
2 Leo Barnhorst 193.0 86.0 University of Notre Dame 1924.0 NaN NaN
3 Ed Bartels 196.0 88.0 North Carolina State University 1925.0 NaN NaN
4 Ralph Beard 178.0 79.0 University of Kentucky 1927.0 Hardinsburg Kentucky
5 Gene Berce 180.0 79.0 Marquette University 1926.0 NaN NaN
6 Charlie Black 196.0 90.0 University of Kansas 1921.0 Arco Idaho
7 Nelson Bobb 183.0 77.0 Temple University 1924.0 Philadelphia Pennsylvania
8 Jake Bornheimer 196.0 90.0 Muhlenberg College 1927.0 New Brunswick New Jersey
9 Vince Boryla 196.0 95.0 University of Denver 1927.0 East Chicago Indiana

We merge both tables, and do some data cleaning:

  • Keep only players with more than 400 minutes for each season (with a 82 games regular season, thats around 5 minutes per game. Players with less than that will be only anecdotical, and will distort the analysis).
  • Replace the * sign in some of the names
  • For the stats that represent total values (others, as TS%, represent percentages), we will take the values per 36 minutes. The reason is to judge every player according to his characteristics, not the time he was on the floor.

In [839]:
data = pd.merge(stats_clean, players[['Player', 'height', 'weight']], left_on='Player', right_on='Player', right_index=False,
      how='left', sort=False).fillna(value=0)
data = data[~(data['Pos']==0) & (data['MP'] > 200)]
data.reset_index(inplace=True, drop=True)
data['Player'] = data['Player'].str.replace('*','')

totals = ['PER', 'OWS', 'DWS', 'WS', 'OBPM', 'DBPM', 'BPM', 'VORP', 'FG', 'FGA', '3P', '3PA', '2P', '2PA', 'FT', 'FTA',
         'ORB', 'DRB', 'TRB', 'AST', 'STL', 'BLK', 'TOV', 'PF', 'PTS']

for col in totals:
    data[col] = 36 * data[col] / data['MP']

In [840]:
data.tail()


Out[840]:
Year Player Pos Age G GS MP PER TS% 3PAr ... DRB TRB AST STL BLK TOV PF PTS height weight
19695 2017.0 Thaddeus Young PF 28.0 74.0 74.0 2237.0 0.239785 0.562 0.172 ... 5.117568 7.225749 1.963344 1.834600 0.482789 1.544926 2.172553 13.099687 203.0 100.0
19696 2017.0 Cody Zeller PF 24.0 62.0 58.0 1725.0 0.348522 0.604 0.002 ... 5.634783 8.452174 2.066087 1.293913 1.210435 1.356522 3.944348 13.335652 213.0 108.0
19697 2017.0 Tyler Zeller C 27.0 51.0 5.0 525.0 0.891429 0.508 0.006 ... 5.554286 8.502857 2.880000 0.480000 1.440000 1.371429 4.182857 12.205714 213.0 114.0
19698 2017.0 Paul Zipser SF 22.0 44.0 18.0 843.0 0.294662 0.503 0.448 ... 4.697509 5.338078 1.537367 0.640569 0.683274 1.708185 3.330961 10.249110 203.0 97.0
19699 2017.0 Ivica Zubac C 19.0 38.0 11.0 609.0 1.004926 0.547 0.013 ... 6.975369 9.399015 1.773399 0.827586 1.950739 1.773399 3.901478 16.788177 216.0 120.0

5 rows × 51 columns

We will train a neural network with this data, to try to predict the position of each player.

A way we didn't follow was to transform the positions into numbers from 1 to 5 (1 for a PG, 2 for a SG, 1.5 for a PG-SG, and so on, until 5 for a C), and use the network for regression instead of classification. But we wanted to see if the network was able to predict labels as "SG-PF", so we decided to work with the categorical labels. Another reason is that this makes this study more easily portable to other areas.

We convert our DataFrame into a matrix X with the inputs, and a vector y with the labels. We scale the inputs and encode the outputs into dummy variables using the corresponding sklearn utilities.

Instead of a stochastic partition, we decided to use the 2017 season as our test data, and all the previous as the train set.


In [842]:
X = data.drop(['Player', 'Pos', 'G', 'GS', 'MP'], axis=1).as_matrix()
y = data['Pos'].as_matrix()

encoder = LabelBinarizer()
y_cat = encoder.fit_transform(y)
nlabels = len(encoder.classes_)

scaler =StandardScaler()
Xnorm = scaler.fit_transform(X)

stats2017 = (data['Year'] == 2017)
X_train = Xnorm[~stats2017]
y_train = y_cat[~stats2017]
X_test = Xnorm[stats2017]
y_test = y_cat[stats2017]

Neural network training

We build using Keras (with Tensorflow as beckend) a neural network with two hidden layers. We will use relu activations, except for the last one, where we use a softmax to properly obtain the label probability. We will use a 20% of the data as a validation set, to make sure we are not overfitting.


In [851]:
model = Sequential()
model.add(Dense(40, activation='relu', input_dim=46))
model.add(Dropout(0.5))
model.add(Dense(30, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(nlabels, activation='softmax'))

In [853]:
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])

In [854]:
# x_train and y_train are Numpy arrays --just like in the Scikit-Learn API.
model.fit(X_train, y_train, epochs=200, batch_size=128, validation_split=0.2, verbose=1)


Train on 15378 samples, validate on 3845 samples
Epoch 1/200
15378/15378 [==============================] - 1s - loss: 2.8803 - acc: 0.1578 - val_loss: 1.9745 - val_acc: 0.4107
Epoch 2/200
15378/15378 [==============================] - 0s - loss: 2.0452 - acc: 0.3210 - val_loss: 1.4504 - val_acc: 0.4661
Epoch 3/200
15378/15378 [==============================] - 0s - loss: 1.6946 - acc: 0.3707 - val_loss: 1.2529 - val_acc: 0.5394
Epoch 4/200
15378/15378 [==============================] - 0s - loss: 1.5110 - acc: 0.4004 - val_loss: 1.1616 - val_acc: 0.5664
Epoch 5/200
15378/15378 [==============================] - 0s - loss: 1.3971 - acc: 0.4282 - val_loss: 1.1100 - val_acc: 0.6031
Epoch 6/200
15378/15378 [==============================] - 0s - loss: 1.3392 - acc: 0.4400 - val_loss: 1.0867 - val_acc: 0.6343
Epoch 7/200
15378/15378 [==============================] - 0s - loss: 1.2855 - acc: 0.4607 - val_loss: 1.0710 - val_acc: 0.6502
Epoch 8/200
15378/15378 [==============================] - 0s - loss: 1.2508 - acc: 0.4808 - val_loss: 1.0556 - val_acc: 0.6364
Epoch 9/200
15378/15378 [==============================] - 0s - loss: 1.2192 - acc: 0.4835 - val_loss: 1.0575 - val_acc: 0.6518
Epoch 10/200
15378/15378 [==============================] - 0s - loss: 1.1847 - acc: 0.5014 - val_loss: 1.0365 - val_acc: 0.6689
Epoch 11/200
15378/15378 [==============================] - 0s - loss: 1.1752 - acc: 0.5105 - val_loss: 1.0345 - val_acc: 0.6627
Epoch 12/200
15378/15378 [==============================] - 0s - loss: 1.1432 - acc: 0.5209 - val_loss: 1.0213 - val_acc: 0.6635
Epoch 13/200
15378/15378 [==============================] - 0s - loss: 1.1337 - acc: 0.5254 - val_loss: 1.0245 - val_acc: 0.6668
Epoch 14/200
15378/15378 [==============================] - 0s - loss: 1.1146 - acc: 0.5313 - val_loss: 1.0121 - val_acc: 0.6715
Epoch 15/200
15378/15378 [==============================] - 0s - loss: 1.1045 - acc: 0.5416 - val_loss: 1.0194 - val_acc: 0.6544
Epoch 16/200
15378/15378 [==============================] - 0s - loss: 1.0943 - acc: 0.5451 - val_loss: 1.0252 - val_acc: 0.6533
Epoch 17/200
15378/15378 [==============================] - 0s - loss: 1.0931 - acc: 0.5430 - val_loss: 1.0063 - val_acc: 0.6679
Epoch 18/200
15378/15378 [==============================] - 0s - loss: 1.0771 - acc: 0.5486 - val_loss: 1.0010 - val_acc: 0.6694
Epoch 19/200
15378/15378 [==============================] - 0s - loss: 1.0685 - acc: 0.5513 - val_loss: 1.0011 - val_acc: 0.6624
Epoch 20/200
15378/15378 [==============================] - 0s - loss: 1.0587 - acc: 0.5583 - val_loss: 0.9910 - val_acc: 0.6666
Epoch 21/200
15378/15378 [==============================] - 0s - loss: 1.0556 - acc: 0.5655 - val_loss: 0.9871 - val_acc: 0.6767
Epoch 22/200
15378/15378 [==============================] - 0s - loss: 1.0433 - acc: 0.5668 - val_loss: 0.9917 - val_acc: 0.6715
Epoch 23/200
15378/15378 [==============================] - 0s - loss: 1.0419 - acc: 0.5689 - val_loss: 0.9779 - val_acc: 0.6705
Epoch 24/200
15378/15378 [==============================] - 0s - loss: 1.0312 - acc: 0.5742 - val_loss: 0.9855 - val_acc: 0.6754
Epoch 25/200
15378/15378 [==============================] - 0s - loss: 1.0329 - acc: 0.5699 - val_loss: 0.9770 - val_acc: 0.6765
Epoch 26/200
15378/15378 [==============================] - 0s - loss: 1.0379 - acc: 0.5678 - val_loss: 0.9869 - val_acc: 0.6463
Epoch 27/200
15378/15378 [==============================] - 0s - loss: 1.0217 - acc: 0.5832 - val_loss: 0.9847 - val_acc: 0.6606
Epoch 28/200
15378/15378 [==============================] - 0s - loss: 1.0230 - acc: 0.5789 - val_loss: 0.9795 - val_acc: 0.6801
Epoch 29/200
15378/15378 [==============================] - 0s - loss: 1.0237 - acc: 0.5779 - val_loss: 0.9777 - val_acc: 0.6791
Epoch 30/200
15378/15378 [==============================] - 0s - loss: 1.0117 - acc: 0.5856 - val_loss: 0.9694 - val_acc: 0.6762
Epoch 31/200
15378/15378 [==============================] - 0s - loss: 1.0108 - acc: 0.5798 - val_loss: 0.9634 - val_acc: 0.6720
Epoch 32/200
15378/15378 [==============================] - 0s - loss: 1.0079 - acc: 0.5931 - val_loss: 0.9608 - val_acc: 0.6687
Epoch 33/200
15378/15378 [==============================] - 0s - loss: 1.0005 - acc: 0.5910 - val_loss: 0.9637 - val_acc: 0.6666
Epoch 34/200
15378/15378 [==============================] - 0s - loss: 0.9990 - acc: 0.5951 - val_loss: 0.9625 - val_acc: 0.6765
Epoch 35/200
15378/15378 [==============================] - 0s - loss: 0.9981 - acc: 0.5901 - val_loss: 0.9537 - val_acc: 0.6710
Epoch 36/200
15378/15378 [==============================] - 0s - loss: 0.9973 - acc: 0.5897 - val_loss: 0.9637 - val_acc: 0.6746
Epoch 37/200
15378/15378 [==============================] - 0s - loss: 0.9909 - acc: 0.5970 - val_loss: 0.9533 - val_acc: 0.6726
Epoch 38/200
15378/15378 [==============================] - 0s - loss: 0.9864 - acc: 0.5976 - val_loss: 0.9606 - val_acc: 0.6817
Epoch 39/200
15378/15378 [==============================] - 0s - loss: 0.9822 - acc: 0.6025 - val_loss: 0.9549 - val_acc: 0.6819
Epoch 40/200
15378/15378 [==============================] - 0s - loss: 0.9864 - acc: 0.5979 - val_loss: 0.9475 - val_acc: 0.6744
Epoch 41/200
15378/15378 [==============================] - 0s - loss: 0.9798 - acc: 0.6010 - val_loss: 0.9476 - val_acc: 0.6687
Epoch 42/200
15378/15378 [==============================] - 0s - loss: 0.9764 - acc: 0.5987 - val_loss: 0.9479 - val_acc: 0.6650
Epoch 43/200
15378/15378 [==============================] - 0s - loss: 0.9791 - acc: 0.6012 - val_loss: 0.9558 - val_acc: 0.6830
Epoch 44/200
15378/15378 [==============================] - 0s - loss: 0.9780 - acc: 0.6004 - val_loss: 0.9455 - val_acc: 0.6757
Epoch 45/200
15378/15378 [==============================] - 0s - loss: 0.9745 - acc: 0.6001 - val_loss: 0.9574 - val_acc: 0.6754
Epoch 46/200
15378/15378 [==============================] - 0s - loss: 0.9722 - acc: 0.6020 - val_loss: 0.9449 - val_acc: 0.6804
Epoch 47/200
15378/15378 [==============================] - 0s - loss: 0.9669 - acc: 0.6087 - val_loss: 0.9541 - val_acc: 0.6590
Epoch 48/200
15378/15378 [==============================] - 0s - loss: 0.9647 - acc: 0.6072 - val_loss: 0.9358 - val_acc: 0.6720
Epoch 49/200
15378/15378 [==============================] - 0s - loss: 0.9617 - acc: 0.6056 - val_loss: 0.9390 - val_acc: 0.6702
Epoch 50/200
15378/15378 [==============================] - 0s - loss: 0.9627 - acc: 0.6043 - val_loss: 0.9378 - val_acc: 0.6861
Epoch 51/200
15378/15378 [==============================] - 0s - loss: 0.9610 - acc: 0.6102 - val_loss: 0.9418 - val_acc: 0.6624
Epoch 52/200
15378/15378 [==============================] - 0s - loss: 0.9532 - acc: 0.6139 - val_loss: 0.9383 - val_acc: 0.6775
Epoch 53/200
15378/15378 [==============================] - 0s - loss: 0.9469 - acc: 0.6113 - val_loss: 0.9354 - val_acc: 0.6817
Epoch 54/200
15378/15378 [==============================] - 0s - loss: 0.9455 - acc: 0.6134 - val_loss: 0.9344 - val_acc: 0.6707
Epoch 55/200
15378/15378 [==============================] - 0s - loss: 0.9450 - acc: 0.6093 - val_loss: 0.9384 - val_acc: 0.6913
Epoch 56/200
15378/15378 [==============================] - 0s - loss: 0.9463 - acc: 0.6169 - val_loss: 0.9437 - val_acc: 0.6814
Epoch 57/200
15378/15378 [==============================] - 0s - loss: 0.9502 - acc: 0.6059 - val_loss: 0.9331 - val_acc: 0.6887
Epoch 58/200
15378/15378 [==============================] - 0s - loss: 0.9431 - acc: 0.6167 - val_loss: 0.9288 - val_acc: 0.6843
Epoch 59/200
15378/15378 [==============================] - 0s - loss: 0.9338 - acc: 0.6182 - val_loss: 0.9364 - val_acc: 0.6895
Epoch 60/200
15378/15378 [==============================] - 0s - loss: 0.9538 - acc: 0.6164 - val_loss: 0.9268 - val_acc: 0.6835
Epoch 61/200
15378/15378 [==============================] - 0s - loss: 0.9384 - acc: 0.6141 - val_loss: 0.9444 - val_acc: 0.6850
Epoch 62/200
15378/15378 [==============================] - 0s - loss: 0.9386 - acc: 0.6270 - val_loss: 0.9290 - val_acc: 0.6762
Epoch 63/200
15378/15378 [==============================] - 0s - loss: 0.9388 - acc: 0.6232 - val_loss: 0.9283 - val_acc: 0.6780
Epoch 64/200
15378/15378 [==============================] - 0s - loss: 0.9378 - acc: 0.6192 - val_loss: 0.9248 - val_acc: 0.6663
Epoch 65/200
15378/15378 [==============================] - 0s - loss: 0.9353 - acc: 0.6245 - val_loss: 0.9239 - val_acc: 0.6770
Epoch 66/200
15378/15378 [==============================] - 0s - loss: 0.9244 - acc: 0.6318 - val_loss: 0.9230 - val_acc: 0.6700
Epoch 67/200
15378/15378 [==============================] - 0s - loss: 0.9370 - acc: 0.6211 - val_loss: 0.9182 - val_acc: 0.6796
Epoch 68/200
15378/15378 [==============================] - 0s - loss: 0.9343 - acc: 0.6192 - val_loss: 0.9230 - val_acc: 0.6900
Epoch 69/200
15378/15378 [==============================] - 0s - loss: 0.9301 - acc: 0.6221 - val_loss: 0.9368 - val_acc: 0.6687
Epoch 70/200
15378/15378 [==============================] - 0s - loss: 0.9159 - acc: 0.6281 - val_loss: 0.9221 - val_acc: 0.6697
Epoch 71/200
15378/15378 [==============================] - 0s - loss: 0.9229 - acc: 0.6288 - val_loss: 0.9239 - val_acc: 0.6923
Epoch 72/200
15378/15378 [==============================] - 0s - loss: 0.9236 - acc: 0.6215 - val_loss: 0.9175 - val_acc: 0.6726
Epoch 73/200
15378/15378 [==============================] - 0s - loss: 0.9296 - acc: 0.6254 - val_loss: 0.9120 - val_acc: 0.6746
Epoch 74/200
15378/15378 [==============================] - 0s - loss: 0.9258 - acc: 0.6250 - val_loss: 0.9172 - val_acc: 0.6936
Epoch 75/200
15378/15378 [==============================] - 0s - loss: 0.9193 - acc: 0.6271 - val_loss: 0.9177 - val_acc: 0.6752
Epoch 76/200
15378/15378 [==============================] - 0s - loss: 0.9168 - acc: 0.6335 - val_loss: 0.9113 - val_acc: 0.6765
Epoch 77/200
15378/15378 [==============================] - 0s - loss: 0.9163 - acc: 0.6311 - val_loss: 0.9156 - val_acc: 0.6908
Epoch 78/200
15378/15378 [==============================] - 0s - loss: 0.9194 - acc: 0.6283 - val_loss: 0.9111 - val_acc: 0.6879
Epoch 79/200
15378/15378 [==============================] - 0s - loss: 0.9185 - acc: 0.6297 - val_loss: 0.9101 - val_acc: 0.6908
Epoch 80/200
15378/15378 [==============================] - 0s - loss: 0.9185 - acc: 0.6245 - val_loss: 0.9072 - val_acc: 0.6814
Epoch 81/200
15378/15378 [==============================] - 0s - loss: 0.9128 - acc: 0.6332 - val_loss: 0.9073 - val_acc: 0.6804
Epoch 82/200
15378/15378 [==============================] - 0s - loss: 0.9096 - acc: 0.6355 - val_loss: 0.9034 - val_acc: 0.6822
Epoch 83/200
15378/15378 [==============================] - 0s - loss: 0.9124 - acc: 0.6314 - val_loss: 0.9032 - val_acc: 0.6923
Epoch 84/200
15378/15378 [==============================] - 0s - loss: 0.9180 - acc: 0.6275 - val_loss: 0.9061 - val_acc: 0.6970
Epoch 85/200
15378/15378 [==============================] - 0s - loss: 0.9113 - acc: 0.6314 - val_loss: 0.9032 - val_acc: 0.6931
Epoch 86/200
15378/15378 [==============================] - 0s - loss: 0.9046 - acc: 0.6362 - val_loss: 0.9006 - val_acc: 0.6843
Epoch 87/200
15378/15378 [==============================] - 0s - loss: 0.9088 - acc: 0.6307 - val_loss: 0.9023 - val_acc: 0.6923
Epoch 88/200
15378/15378 [==============================] - 0s - loss: 0.9003 - acc: 0.6353 - val_loss: 0.9001 - val_acc: 0.6947
Epoch 89/200
15378/15378 [==============================] - 0s - loss: 0.8992 - acc: 0.6371 - val_loss: 0.9020 - val_acc: 0.6947
Epoch 90/200
15378/15378 [==============================] - 0s - loss: 0.9130 - acc: 0.6347 - val_loss: 0.8998 - val_acc: 0.6710
Epoch 91/200
15378/15378 [==============================] - 0s - loss: 0.9102 - acc: 0.6364 - val_loss: 0.9070 - val_acc: 0.6923
Epoch 92/200
15378/15378 [==============================] - 0s - loss: 0.9076 - acc: 0.6366 - val_loss: 0.8971 - val_acc: 0.6892
Epoch 93/200
15378/15378 [==============================] - 0s - loss: 0.9066 - acc: 0.6329 - val_loss: 0.9104 - val_acc: 0.6874
Epoch 94/200
15378/15378 [==============================] - 0s - loss: 0.8994 - acc: 0.6405 - val_loss: 0.9086 - val_acc: 0.6809
Epoch 95/200
15378/15378 [==============================] - 0s - loss: 0.8897 - acc: 0.6380 - val_loss: 0.8921 - val_acc: 0.6871
Epoch 96/200
15378/15378 [==============================] - 0s - loss: 0.8914 - acc: 0.6438 - val_loss: 0.8923 - val_acc: 0.6754
Epoch 97/200
15378/15378 [==============================] - 0s - loss: 0.8952 - acc: 0.6472 - val_loss: 0.8935 - val_acc: 0.6757
Epoch 98/200
15378/15378 [==============================] - 0s - loss: 0.8945 - acc: 0.6404 - val_loss: 0.8927 - val_acc: 0.6897
Epoch 99/200
15378/15378 [==============================] - 0s - loss: 0.9008 - acc: 0.6434 - val_loss: 0.8978 - val_acc: 0.6897
Epoch 100/200
15378/15378 [==============================] - 0s - loss: 0.8926 - acc: 0.6369 - val_loss: 0.8980 - val_acc: 0.6921
Epoch 101/200
15378/15378 [==============================] - 0s - loss: 0.8965 - acc: 0.6427 - val_loss: 0.8875 - val_acc: 0.6861
Epoch 102/200
15378/15378 [==============================] - 0s - loss: 0.8896 - acc: 0.6442 - val_loss: 0.8865 - val_acc: 0.6967
Epoch 103/200
15378/15378 [==============================] - 0s - loss: 0.8893 - acc: 0.6457 - val_loss: 0.8854 - val_acc: 0.6897
Epoch 104/200
15378/15378 [==============================] - 0s - loss: 0.8837 - acc: 0.6459 - val_loss: 0.8850 - val_acc: 0.6954
Epoch 105/200
15378/15378 [==============================] - 0s - loss: 0.8882 - acc: 0.6449 - val_loss: 0.8952 - val_acc: 0.6908
Epoch 106/200
15378/15378 [==============================] - 0s - loss: 0.8831 - acc: 0.6496 - val_loss: 0.8822 - val_acc: 0.6874
Epoch 107/200
15378/15378 [==============================] - 0s - loss: 0.8893 - acc: 0.6444 - val_loss: 0.8825 - val_acc: 0.6785
Epoch 108/200
15378/15378 [==============================] - 0s - loss: 0.8845 - acc: 0.6457 - val_loss: 0.8855 - val_acc: 0.7020
Epoch 109/200
15378/15378 [==============================] - 0s - loss: 0.8806 - acc: 0.6490 - val_loss: 0.8782 - val_acc: 0.6973
Epoch 110/200
15378/15378 [==============================] - 0s - loss: 0.8815 - acc: 0.6471 - val_loss: 0.8807 - val_acc: 0.6973
Epoch 111/200
15378/15378 [==============================] - 0s - loss: 0.8833 - acc: 0.6472 - val_loss: 0.8798 - val_acc: 0.6970
Epoch 112/200
15378/15378 [==============================] - 0s - loss: 0.8763 - acc: 0.6466 - val_loss: 0.8780 - val_acc: 0.6949
Epoch 113/200
15378/15378 [==============================] - 0s - loss: 0.8729 - acc: 0.6533 - val_loss: 0.8862 - val_acc: 0.6778
Epoch 114/200
15378/15378 [==============================] - 0s - loss: 0.8777 - acc: 0.6540 - val_loss: 0.8804 - val_acc: 0.7014
Epoch 115/200
15378/15378 [==============================] - 0s - loss: 0.8744 - acc: 0.6488 - val_loss: 0.8843 - val_acc: 0.7017
Epoch 116/200
15378/15378 [==============================] - 0s - loss: 0.8767 - acc: 0.6507 - val_loss: 0.8754 - val_acc: 0.6895
Epoch 117/200
15378/15378 [==============================] - 0s - loss: 0.8833 - acc: 0.6485 - val_loss: 0.8749 - val_acc: 0.6798
Epoch 118/200
15378/15378 [==============================] - 0s - loss: 0.8802 - acc: 0.6462 - val_loss: 0.8719 - val_acc: 0.6915
Epoch 119/200
15378/15378 [==============================] - 0s - loss: 0.8801 - acc: 0.6443 - val_loss: 0.8760 - val_acc: 0.6991
Epoch 120/200
15378/15378 [==============================] - 0s - loss: 0.8670 - acc: 0.6578 - val_loss: 0.8948 - val_acc: 0.6752
Epoch 121/200
15378/15378 [==============================] - 0s - loss: 0.8775 - acc: 0.6450 - val_loss: 0.8822 - val_acc: 0.6921
Epoch 122/200
15378/15378 [==============================] - 0s - loss: 0.8708 - acc: 0.6515 - val_loss: 0.8727 - val_acc: 0.6895
Epoch 123/200
15378/15378 [==============================] - 0s - loss: 0.8698 - acc: 0.6515 - val_loss: 0.8698 - val_acc: 0.6897
Epoch 124/200
15378/15378 [==============================] - 0s - loss: 0.8759 - acc: 0.6540 - val_loss: 0.8661 - val_acc: 0.6936
Epoch 125/200
15378/15378 [==============================] - 0s - loss: 0.8641 - acc: 0.6550 - val_loss: 0.8686 - val_acc: 0.7007
Epoch 126/200
15378/15378 [==============================] - 0s - loss: 0.8752 - acc: 0.6528 - val_loss: 0.8728 - val_acc: 0.7017
Epoch 127/200
15378/15378 [==============================] - 0s - loss: 0.8659 - acc: 0.6550 - val_loss: 0.8731 - val_acc: 0.6793
Epoch 128/200
15378/15378 [==============================] - 0s - loss: 0.8650 - acc: 0.6513 - val_loss: 0.8644 - val_acc: 0.7009
Epoch 129/200
15378/15378 [==============================] - 0s - loss: 0.8682 - acc: 0.6530 - val_loss: 0.8671 - val_acc: 0.6921
Epoch 130/200
15378/15378 [==============================] - 0s - loss: 0.8673 - acc: 0.6528 - val_loss: 0.8667 - val_acc: 0.7009
Epoch 131/200
15378/15378 [==============================] - 0s - loss: 0.8637 - acc: 0.6570 - val_loss: 0.8679 - val_acc: 0.7004
Epoch 132/200
15378/15378 [==============================] - 0s - loss: 0.8625 - acc: 0.6587 - val_loss: 0.8677 - val_acc: 0.6941
Epoch 133/200
15378/15378 [==============================] - 0s - loss: 0.8666 - acc: 0.6592 - val_loss: 0.8644 - val_acc: 0.7009
Epoch 134/200
15378/15378 [==============================] - 0s - loss: 0.8608 - acc: 0.6572 - val_loss: 0.8663 - val_acc: 0.6936
Epoch 135/200
15378/15378 [==============================] - 0s - loss: 0.8648 - acc: 0.6564 - val_loss: 0.8669 - val_acc: 0.7038
Epoch 136/200
15378/15378 [==============================] - 0s - loss: 0.8599 - acc: 0.6606 - val_loss: 0.8650 - val_acc: 0.7048
Epoch 137/200
15378/15378 [==============================] - 0s - loss: 0.8541 - acc: 0.6673 - val_loss: 0.8645 - val_acc: 0.7040
Epoch 138/200
15378/15378 [==============================] - 0s - loss: 0.8611 - acc: 0.6587 - val_loss: 0.8626 - val_acc: 0.7033
Epoch 139/200
15378/15378 [==============================] - 0s - loss: 0.8567 - acc: 0.6609 - val_loss: 0.8650 - val_acc: 0.7074
Epoch 140/200
15378/15378 [==============================] - 0s - loss: 0.8560 - acc: 0.6617 - val_loss: 0.8584 - val_acc: 0.6910
Epoch 141/200
15378/15378 [==============================] - 0s - loss: 0.8532 - acc: 0.6648 - val_loss: 0.8583 - val_acc: 0.6999
Epoch 142/200
15378/15378 [==============================] - 0s - loss: 0.8569 - acc: 0.6646 - val_loss: 0.8592 - val_acc: 0.6926
Epoch 143/200
15378/15378 [==============================] - 0s - loss: 0.8529 - acc: 0.6627 - val_loss: 0.8649 - val_acc: 0.7033
Epoch 144/200
15378/15378 [==============================] - 0s - loss: 0.8608 - acc: 0.6585 - val_loss: 0.8699 - val_acc: 0.7025
Epoch 145/200
15378/15378 [==============================] - 0s - loss: 0.8508 - acc: 0.6624 - val_loss: 0.8570 - val_acc: 0.7012
Epoch 146/200
15378/15378 [==============================] - 0s - loss: 0.8519 - acc: 0.6595 - val_loss: 0.8622 - val_acc: 0.7061
Epoch 147/200
15378/15378 [==============================] - 0s - loss: 0.8482 - acc: 0.6626 - val_loss: 0.8541 - val_acc: 0.7033
Epoch 148/200
15378/15378 [==============================] - 0s - loss: 0.8506 - acc: 0.6655 - val_loss: 0.8560 - val_acc: 0.6908
Epoch 149/200
15378/15378 [==============================] - 0s - loss: 0.8486 - acc: 0.6658 - val_loss: 0.8547 - val_acc: 0.6939
Epoch 150/200
15378/15378 [==============================] - 0s - loss: 0.8485 - acc: 0.6641 - val_loss: 0.8572 - val_acc: 0.6952
Epoch 151/200
15378/15378 [==============================] - 0s - loss: 0.8521 - acc: 0.6596 - val_loss: 0.8555 - val_acc: 0.7048
Epoch 152/200
15378/15378 [==============================] - 0s - loss: 0.8428 - acc: 0.6680 - val_loss: 0.8562 - val_acc: 0.7072
Epoch 153/200
15378/15378 [==============================] - 0s - loss: 0.8444 - acc: 0.6680 - val_loss: 0.8533 - val_acc: 0.7033
Epoch 154/200
15378/15378 [==============================] - 0s - loss: 0.8443 - acc: 0.6680 - val_loss: 0.8535 - val_acc: 0.7053
Epoch 155/200
15378/15378 [==============================] - 0s - loss: 0.8453 - acc: 0.6671 - val_loss: 0.8508 - val_acc: 0.7001
Epoch 156/200
15378/15378 [==============================] - 0s - loss: 0.8516 - acc: 0.6630 - val_loss: 0.8522 - val_acc: 0.6954
Epoch 157/200
15378/15378 [==============================] - 0s - loss: 0.8437 - acc: 0.6674 - val_loss: 0.8518 - val_acc: 0.7004
Epoch 158/200
15378/15378 [==============================] - 0s - loss: 0.8409 - acc: 0.6642 - val_loss: 0.8513 - val_acc: 0.6970
Epoch 159/200
15378/15378 [==============================] - 0s - loss: 0.8419 - acc: 0.6687 - val_loss: 0.8493 - val_acc: 0.7048
Epoch 160/200
15378/15378 [==============================] - 0s - loss: 0.8467 - acc: 0.6635 - val_loss: 0.8508 - val_acc: 0.6999
Epoch 161/200
15378/15378 [==============================] - 0s - loss: 0.8412 - acc: 0.6641 - val_loss: 0.8534 - val_acc: 0.6996
Epoch 162/200
15378/15378 [==============================] - 0s - loss: 0.8505 - acc: 0.6643 - val_loss: 0.8500 - val_acc: 0.6980
Epoch 163/200
15378/15378 [==============================] - 0s - loss: 0.8427 - acc: 0.6691 - val_loss: 0.8482 - val_acc: 0.7025
Epoch 164/200
15378/15378 [==============================] - 0s - loss: 0.8317 - acc: 0.6725 - val_loss: 0.8471 - val_acc: 0.7051
Epoch 165/200
15378/15378 [==============================] - 0s - loss: 0.8399 - acc: 0.6697 - val_loss: 0.8471 - val_acc: 0.7043
Epoch 166/200
15378/15378 [==============================] - 0s - loss: 0.8363 - acc: 0.6684 - val_loss: 0.8507 - val_acc: 0.7059
Epoch 167/200
15378/15378 [==============================] - 0s - loss: 0.8464 - acc: 0.6672 - val_loss: 0.8448 - val_acc: 0.6999
Epoch 168/200
15378/15378 [==============================] - 0s - loss: 0.8461 - acc: 0.6670 - val_loss: 0.8479 - val_acc: 0.7053
Epoch 169/200
15378/15378 [==============================] - 0s - loss: 0.8389 - acc: 0.6676 - val_loss: 0.8427 - val_acc: 0.7033
Epoch 170/200
15378/15378 [==============================] - 0s - loss: 0.8347 - acc: 0.6735 - val_loss: 0.8465 - val_acc: 0.7046
Epoch 171/200
15378/15378 [==============================] - 0s - loss: 0.8371 - acc: 0.6681 - val_loss: 0.8456 - val_acc: 0.7025
Epoch 172/200
15378/15378 [==============================] - 0s - loss: 0.8290 - acc: 0.6766 - val_loss: 0.8459 - val_acc: 0.6993
Epoch 173/200
15378/15378 [==============================] - 0s - loss: 0.8405 - acc: 0.6708 - val_loss: 0.8450 - val_acc: 0.7022
Epoch 174/200
15378/15378 [==============================] - 0s - loss: 0.8373 - acc: 0.6678 - val_loss: 0.8439 - val_acc: 0.7040
Epoch 175/200
15378/15378 [==============================] - 0s - loss: 0.8379 - acc: 0.6713 - val_loss: 0.8524 - val_acc: 0.6993
Epoch 176/200
15378/15378 [==============================] - 0s - loss: 0.8353 - acc: 0.6719 - val_loss: 0.8413 - val_acc: 0.7056
Epoch 177/200
15378/15378 [==============================] - 0s - loss: 0.8358 - acc: 0.6706 - val_loss: 0.8428 - val_acc: 0.7059
Epoch 178/200
15378/15378 [==============================] - 0s - loss: 0.8286 - acc: 0.6702 - val_loss: 0.8450 - val_acc: 0.7025
Epoch 179/200
15378/15378 [==============================] - 0s - loss: 0.8320 - acc: 0.6757 - val_loss: 0.8430 - val_acc: 0.7064
Epoch 180/200
15378/15378 [==============================] - 0s - loss: 0.8221 - acc: 0.6758 - val_loss: 0.8424 - val_acc: 0.6999
Epoch 181/200
15378/15378 [==============================] - 0s - loss: 0.8393 - acc: 0.6714 - val_loss: 0.8366 - val_acc: 0.7022
Epoch 182/200
15378/15378 [==============================] - 0s - loss: 0.8271 - acc: 0.6724 - val_loss: 0.8409 - val_acc: 0.7046
Epoch 183/200
15378/15378 [==============================] - 0s - loss: 0.8377 - acc: 0.6756 - val_loss: 0.8366 - val_acc: 0.6980
Epoch 184/200
15378/15378 [==============================] - 0s - loss: 0.8305 - acc: 0.6748 - val_loss: 0.8376 - val_acc: 0.6944
Epoch 185/200
15378/15378 [==============================] - 0s - loss: 0.8297 - acc: 0.6742 - val_loss: 0.8389 - val_acc: 0.7030
Epoch 186/200
15378/15378 [==============================] - 0s - loss: 0.8291 - acc: 0.6758 - val_loss: 0.8404 - val_acc: 0.7043
Epoch 187/200
15378/15378 [==============================] - 0s - loss: 0.8264 - acc: 0.6741 - val_loss: 0.8442 - val_acc: 0.7009
Epoch 188/200
15378/15378 [==============================] - 0s - loss: 0.8163 - acc: 0.6814 - val_loss: 0.8387 - val_acc: 0.7007
Epoch 189/200
15378/15378 [==============================] - 0s - loss: 0.8237 - acc: 0.6767 - val_loss: 0.8396 - val_acc: 0.7048
Epoch 190/200
15378/15378 [==============================] - 0s - loss: 0.8267 - acc: 0.6777 - val_loss: 0.8359 - val_acc: 0.7056
Epoch 191/200
15378/15378 [==============================] - 0s - loss: 0.8285 - acc: 0.6765 - val_loss: 0.8482 - val_acc: 0.6970
Epoch 192/200
15378/15378 [==============================] - 0s - loss: 0.8233 - acc: 0.6774 - val_loss: 0.8391 - val_acc: 0.7022
Epoch 193/200
15378/15378 [==============================] - 0s - loss: 0.8238 - acc: 0.6794 - val_loss: 0.8343 - val_acc: 0.7035
Epoch 194/200
15378/15378 [==============================] - 0s - loss: 0.8192 - acc: 0.6754 - val_loss: 0.8379 - val_acc: 0.7038
Epoch 195/200
15378/15378 [==============================] - 0s - loss: 0.8210 - acc: 0.6783 - val_loss: 0.8350 - val_acc: 0.7012
Epoch 196/200
15378/15378 [==============================] - 0s - loss: 0.8284 - acc: 0.6766 - val_loss: 0.8364 - val_acc: 0.7022
Epoch 197/200
15378/15378 [==============================] - 0s - loss: 0.8238 - acc: 0.6776 - val_loss: 0.8444 - val_acc: 0.7009
Epoch 198/200
15378/15378 [==============================] - 0s - loss: 0.8159 - acc: 0.6772 - val_loss: 0.8341 - val_acc: 0.7020
Epoch 199/200
15378/15378 [==============================] - 0s - loss: 0.8252 - acc: 0.6816 - val_loss: 0.8349 - val_acc: 0.7038
Epoch 200/200
15378/15378 [==============================] - 0s - loss: 0.8190 - acc: 0.6767 - val_loss: 0.8367 - val_acc: 0.7061
Out[854]:
<keras.callbacks.History at 0x143ce7ac8>

In [855]:
model.test_on_batch(X_test, y_test, sample_weight=None)


Out[855]:
[0.74140817, 0.69601679]

The model performs well both for the validation and the test sets (65% might not seem a lot, but it is satisfying enough for our problem, where all the labels are very subjective (Was Larry Bird a "SM-PF" or a "PF-SF"? Nobody can tell).

Now we train again the model, using all the training data (we will still reserve the 2017 season out of the training).


In [856]:
# Production model, using all data
model.fit(X_train, y_train, epochs=200, batch_size=128, validation_split=0, verbose=1)


Epoch 1/200
19223/19223 [==============================] - 0s - loss: 0.8416 - acc: 0.6743     
Epoch 2/200
19223/19223 [==============================] - 0s - loss: 0.8484 - acc: 0.6783     
Epoch 3/200
19223/19223 [==============================] - 0s - loss: 0.8460 - acc: 0.6733     
Epoch 4/200
19223/19223 [==============================] - 0s - loss: 0.8332 - acc: 0.6786     
Epoch 5/200
19223/19223 [==============================] - 0s - loss: 0.8373 - acc: 0.6799     
Epoch 6/200
19223/19223 [==============================] - 0s - loss: 0.8416 - acc: 0.6742     
Epoch 7/200
19223/19223 [==============================] - 0s - loss: 0.8364 - acc: 0.6770     
Epoch 8/200
19223/19223 [==============================] - 0s - loss: 0.8407 - acc: 0.6744     
Epoch 9/200
19223/19223 [==============================] - 0s - loss: 0.8351 - acc: 0.6754     
Epoch 10/200
19223/19223 [==============================] - 0s - loss: 0.8304 - acc: 0.6786     
Epoch 11/200
19223/19223 [==============================] - 0s - loss: 0.8369 - acc: 0.6747     
Epoch 12/200
19223/19223 [==============================] - 0s - loss: 0.8309 - acc: 0.6798     
Epoch 13/200
19223/19223 [==============================] - 0s - loss: 0.8369 - acc: 0.6813     
Epoch 14/200
19223/19223 [==============================] - 0s - loss: 0.8351 - acc: 0.6779     
Epoch 15/200
19223/19223 [==============================] - 0s - loss: 0.8272 - acc: 0.6858     
Epoch 16/200
19223/19223 [==============================] - 0s - loss: 0.8340 - acc: 0.6770     
Epoch 17/200
19223/19223 [==============================] - 0s - loss: 0.8279 - acc: 0.6789     
Epoch 18/200
19223/19223 [==============================] - 0s - loss: 0.8252 - acc: 0.6788     
Epoch 19/200
19223/19223 [==============================] - 0s - loss: 0.8297 - acc: 0.6768     
Epoch 20/200
19223/19223 [==============================] - 0s - loss: 0.8257 - acc: 0.6797     
Epoch 21/200
19223/19223 [==============================] - 0s - loss: 0.8311 - acc: 0.6812     
Epoch 22/200
19223/19223 [==============================] - 0s - loss: 0.8262 - acc: 0.6822     
Epoch 23/200
19223/19223 [==============================] - 0s - loss: 0.8265 - acc: 0.6794     
Epoch 24/200
19223/19223 [==============================] - 0s - loss: 0.8307 - acc: 0.6787     
Epoch 25/200
19223/19223 [==============================] - 0s - loss: 0.8188 - acc: 0.6855     
Epoch 26/200
19223/19223 [==============================] - 0s - loss: 0.8270 - acc: 0.6812     
Epoch 27/200
19223/19223 [==============================] - 0s - loss: 0.8277 - acc: 0.6815     
Epoch 28/200
19223/19223 [==============================] - 0s - loss: 0.8240 - acc: 0.6826     
Epoch 29/200
19223/19223 [==============================] - 0s - loss: 0.8298 - acc: 0.6829     
Epoch 30/200
19223/19223 [==============================] - 0s - loss: 0.8245 - acc: 0.6829     
Epoch 31/200
19223/19223 [==============================] - 0s - loss: 0.8164 - acc: 0.6847     
Epoch 32/200
19223/19223 [==============================] - 0s - loss: 0.8213 - acc: 0.6819     
Epoch 33/200
19223/19223 [==============================] - 0s - loss: 0.8260 - acc: 0.6824     
Epoch 34/200
19223/19223 [==============================] - 0s - loss: 0.8271 - acc: 0.6756     
Epoch 35/200
19223/19223 [==============================] - 0s - loss: 0.8208 - acc: 0.6854     
Epoch 36/200
19223/19223 [==============================] - 0s - loss: 0.8185 - acc: 0.6883     
Epoch 37/200
19223/19223 [==============================] - 0s - loss: 0.8201 - acc: 0.6878     
Epoch 38/200
19223/19223 [==============================] - 0s - loss: 0.8208 - acc: 0.6858     
Epoch 39/200
19223/19223 [==============================] - 0s - loss: 0.8143 - acc: 0.6884     
Epoch 40/200
19223/19223 [==============================] - 0s - loss: 0.8136 - acc: 0.6872     
Epoch 41/200
19223/19223 [==============================] - 0s - loss: 0.8187 - acc: 0.6823     
Epoch 42/200
19223/19223 [==============================] - 0s - loss: 0.8139 - acc: 0.6887     
Epoch 43/200
19223/19223 [==============================] - 0s - loss: 0.8195 - acc: 0.6856     
Epoch 44/200
19223/19223 [==============================] - 0s - loss: 0.8131 - acc: 0.6856     
Epoch 45/200
19223/19223 [==============================] - 0s - loss: 0.8148 - acc: 0.6895     
Epoch 46/200
19223/19223 [==============================] - 0s - loss: 0.8097 - acc: 0.6878     
Epoch 47/200
19223/19223 [==============================] - 0s - loss: 0.8165 - acc: 0.6894     
Epoch 48/200
19223/19223 [==============================] - 0s - loss: 0.8104 - acc: 0.6870     
Epoch 49/200
19223/19223 [==============================] - 0s - loss: 0.8102 - acc: 0.6891     
Epoch 50/200
19223/19223 [==============================] - 0s - loss: 0.8149 - acc: 0.6853     
Epoch 51/200
19223/19223 [==============================] - 0s - loss: 0.8129 - acc: 0.6902     
Epoch 52/200
19223/19223 [==============================] - 0s - loss: 0.8149 - acc: 0.6908     
Epoch 53/200
19223/19223 [==============================] - 0s - loss: 0.8091 - acc: 0.6897     
Epoch 54/200
19223/19223 [==============================] - 0s - loss: 0.8109 - acc: 0.6866     
Epoch 55/200
19223/19223 [==============================] - 0s - loss: 0.8142 - acc: 0.6863     
Epoch 56/200
19223/19223 [==============================] - 0s - loss: 0.8082 - acc: 0.6923     
Epoch 57/200
19223/19223 [==============================] - 0s - loss: 0.8060 - acc: 0.6877     
Epoch 58/200
19223/19223 [==============================] - 0s - loss: 0.8142 - acc: 0.6891     
Epoch 59/200
19223/19223 [==============================] - 0s - loss: 0.8087 - acc: 0.6897     
Epoch 60/200
19223/19223 [==============================] - 0s - loss: 0.8084 - acc: 0.6917     
Epoch 61/200
19223/19223 [==============================] - 0s - loss: 0.8087 - acc: 0.6921     
Epoch 62/200
19223/19223 [==============================] - 0s - loss: 0.8139 - acc: 0.6927     
Epoch 63/200
19223/19223 [==============================] - 0s - loss: 0.8085 - acc: 0.6892     
Epoch 64/200
19223/19223 [==============================] - 0s - loss: 0.8044 - acc: 0.6909     
Epoch 65/200
19223/19223 [==============================] - 0s - loss: 0.8056 - acc: 0.6879     
Epoch 66/200
19223/19223 [==============================] - 0s - loss: 0.8142 - acc: 0.6848     
Epoch 67/200
19223/19223 [==============================] - 0s - loss: 0.8023 - acc: 0.6923     
Epoch 68/200
19223/19223 [==============================] - 0s - loss: 0.8074 - acc: 0.6917     - ETA: 0s - loss: 0.7954 - acc:
Epoch 69/200
19223/19223 [==============================] - 0s - loss: 0.8090 - acc: 0.6919     
Epoch 70/200
19223/19223 [==============================] - 0s - loss: 0.8015 - acc: 0.6907     
Epoch 71/200
19223/19223 [==============================] - 0s - loss: 0.8039 - acc: 0.6923     
Epoch 72/200
19223/19223 [==============================] - 0s - loss: 0.7997 - acc: 0.6933     
Epoch 73/200
19223/19223 [==============================] - 0s - loss: 0.8000 - acc: 0.6961     
Epoch 74/200
19223/19223 [==============================] - 0s - loss: 0.8045 - acc: 0.6940     
Epoch 75/200
19223/19223 [==============================] - 0s - loss: 0.8059 - acc: 0.6954     
Epoch 76/200
19223/19223 [==============================] - 0s - loss: 0.8064 - acc: 0.6921     
Epoch 77/200
19223/19223 [==============================] - 0s - loss: 0.8043 - acc: 0.6923     
Epoch 78/200
19223/19223 [==============================] - 0s - loss: 0.8091 - acc: 0.6900     
Epoch 79/200
19223/19223 [==============================] - 0s - loss: 0.8057 - acc: 0.6947     
Epoch 80/200
19223/19223 [==============================] - 0s - loss: 0.8047 - acc: 0.6965     
Epoch 81/200
19223/19223 [==============================] - 0s - loss: 0.8037 - acc: 0.6958     
Epoch 82/200
19223/19223 [==============================] - 0s - loss: 0.8008 - acc: 0.6949     
Epoch 83/200
19223/19223 [==============================] - 0s - loss: 0.8002 - acc: 0.6954     
Epoch 84/200
19223/19223 [==============================] - 0s - loss: 0.8002 - acc: 0.6980     
Epoch 85/200
19223/19223 [==============================] - 0s - loss: 0.8018 - acc: 0.6954     
Epoch 86/200
19223/19223 [==============================] - 0s - loss: 0.8030 - acc: 0.6973     
Epoch 87/200
19223/19223 [==============================] - 0s - loss: 0.7959 - acc: 0.6958     
Epoch 88/200
19223/19223 [==============================] - 0s - loss: 0.8052 - acc: 0.6933     
Epoch 89/200
19223/19223 [==============================] - 0s - loss: 0.8008 - acc: 0.6944     
Epoch 90/200
19223/19223 [==============================] - 0s - loss: 0.7945 - acc: 0.6982     
Epoch 91/200
19223/19223 [==============================] - 0s - loss: 0.8060 - acc: 0.6917     
Epoch 92/200
19223/19223 [==============================] - 0s - loss: 0.8007 - acc: 0.6935     
Epoch 93/200
19223/19223 [==============================] - 0s - loss: 0.7936 - acc: 0.6942     
Epoch 94/200
19223/19223 [==============================] - 0s - loss: 0.7949 - acc: 0.7004     
Epoch 95/200
19223/19223 [==============================] - 0s - loss: 0.7981 - acc: 0.6956     
Epoch 96/200
19223/19223 [==============================] - 0s - loss: 0.7958 - acc: 0.6986     
Epoch 97/200
19223/19223 [==============================] - 0s - loss: 0.8041 - acc: 0.6958     
Epoch 98/200
19223/19223 [==============================] - 0s - loss: 0.7995 - acc: 0.6931     
Epoch 99/200
19223/19223 [==============================] - 0s - loss: 0.7982 - acc: 0.6955     
Epoch 100/200
19223/19223 [==============================] - 0s - loss: 0.7981 - acc: 0.6960     
Epoch 101/200
19223/19223 [==============================] - 0s - loss: 0.8055 - acc: 0.6947     
Epoch 102/200
19223/19223 [==============================] - 0s - loss: 0.7979 - acc: 0.6946     
Epoch 103/200
19223/19223 [==============================] - 0s - loss: 0.7952 - acc: 0.6972     
Epoch 104/200
19223/19223 [==============================] - 0s - loss: 0.7964 - acc: 0.6949     
Epoch 105/200
19223/19223 [==============================] - 0s - loss: 0.7938 - acc: 0.6988     
Epoch 106/200
19223/19223 [==============================] - 0s - loss: 0.7964 - acc: 0.6993     
Epoch 107/200
19223/19223 [==============================] - 0s - loss: 0.7940 - acc: 0.6979     
Epoch 108/200
19223/19223 [==============================] - 0s - loss: 0.7915 - acc: 0.6968     
Epoch 109/200
19223/19223 [==============================] - 0s - loss: 0.7930 - acc: 0.6933     
Epoch 110/200
19223/19223 [==============================] - 0s - loss: 0.7858 - acc: 0.7012     
Epoch 111/200
19223/19223 [==============================] - 0s - loss: 0.7945 - acc: 0.6983     
Epoch 112/200
19223/19223 [==============================] - 0s - loss: 0.7922 - acc: 0.7011     
Epoch 113/200
19223/19223 [==============================] - 0s - loss: 0.7932 - acc: 0.6957     
Epoch 114/200
19223/19223 [==============================] - 0s - loss: 0.7935 - acc: 0.6948     
Epoch 115/200
19223/19223 [==============================] - 0s - loss: 0.7905 - acc: 0.6966     
Epoch 116/200
19223/19223 [==============================] - 0s - loss: 0.7937 - acc: 0.6995     
Epoch 117/200
19223/19223 [==============================] - 0s - loss: 0.7883 - acc: 0.6948     
Epoch 118/200
19223/19223 [==============================] - 0s - loss: 0.7888 - acc: 0.6979     
Epoch 119/200
19223/19223 [==============================] - 0s - loss: 0.7874 - acc: 0.7022     
Epoch 120/200
19223/19223 [==============================] - 0s - loss: 0.7880 - acc: 0.6998     
Epoch 121/200
19223/19223 [==============================] - 0s - loss: 0.7965 - acc: 0.7020     
Epoch 122/200
19223/19223 [==============================] - 0s - loss: 0.7864 - acc: 0.6978     
Epoch 123/200
19223/19223 [==============================] - 0s - loss: 0.7895 - acc: 0.7021     
Epoch 124/200
19223/19223 [==============================] - 0s - loss: 0.7886 - acc: 0.6989     
Epoch 125/200
19223/19223 [==============================] - 0s - loss: 0.7880 - acc: 0.7000     
Epoch 126/200
19223/19223 [==============================] - 0s - loss: 0.7841 - acc: 0.7047     
Epoch 127/200
19223/19223 [==============================] - 0s - loss: 0.7942 - acc: 0.7020     - ETA: 0s - loss: 0.7756 - acc:
Epoch 128/200
19223/19223 [==============================] - 0s - loss: 0.7894 - acc: 0.7009     
Epoch 129/200
19223/19223 [==============================] - 0s - loss: 0.7955 - acc: 0.6960     
Epoch 130/200
19223/19223 [==============================] - 0s - loss: 0.7852 - acc: 0.7029     
Epoch 131/200
19223/19223 [==============================] - 0s - loss: 0.7895 - acc: 0.6993     
Epoch 132/200
19223/19223 [==============================] - 0s - loss: 0.7914 - acc: 0.7016     
Epoch 133/200
19223/19223 [==============================] - 0s - loss: 0.7862 - acc: 0.7040     
Epoch 134/200
19223/19223 [==============================] - 0s - loss: 0.7888 - acc: 0.6985     
Epoch 135/200
19223/19223 [==============================] - 0s - loss: 0.7904 - acc: 0.7014     
Epoch 136/200
19223/19223 [==============================] - 0s - loss: 0.7891 - acc: 0.7045     
Epoch 137/200
19223/19223 [==============================] - 0s - loss: 0.7838 - acc: 0.7069     
Epoch 138/200
19223/19223 [==============================] - 0s - loss: 0.7848 - acc: 0.7025     
Epoch 139/200
19223/19223 [==============================] - 0s - loss: 0.7844 - acc: 0.6996     
Epoch 140/200
19223/19223 [==============================] - 0s - loss: 0.7818 - acc: 0.7033     
Epoch 141/200
19223/19223 [==============================] - 0s - loss: 0.7872 - acc: 0.7033     
Epoch 142/200
19223/19223 [==============================] - 0s - loss: 0.7895 - acc: 0.6995     
Epoch 143/200
19223/19223 [==============================] - 0s - loss: 0.7851 - acc: 0.7052     
Epoch 144/200
19223/19223 [==============================] - 0s - loss: 0.7809 - acc: 0.7044     
Epoch 145/200
19223/19223 [==============================] - 0s - loss: 0.7852 - acc: 0.7037     
Epoch 146/200
19223/19223 [==============================] - 0s - loss: 0.7904 - acc: 0.6993     
Epoch 147/200
19223/19223 [==============================] - 0s - loss: 0.7879 - acc: 0.7000     
Epoch 148/200
19223/19223 [==============================] - 0s - loss: 0.7868 - acc: 0.6990     
Epoch 149/200
19223/19223 [==============================] - 0s - loss: 0.7870 - acc: 0.7015     
Epoch 150/200
19223/19223 [==============================] - 0s - loss: 0.7812 - acc: 0.7029     
Epoch 151/200
19223/19223 [==============================] - 0s - loss: 0.7866 - acc: 0.7037     
Epoch 152/200
19223/19223 [==============================] - 0s - loss: 0.7857 - acc: 0.7041     
Epoch 153/200
19223/19223 [==============================] - 0s - loss: 0.7875 - acc: 0.7049     
Epoch 154/200
19223/19223 [==============================] - 0s - loss: 0.7785 - acc: 0.7028     
Epoch 155/200
19223/19223 [==============================] - 0s - loss: 0.7807 - acc: 0.7051     
Epoch 156/200
19223/19223 [==============================] - 0s - loss: 0.7920 - acc: 0.6994     
Epoch 157/200
19223/19223 [==============================] - 0s - loss: 0.7910 - acc: 0.6988     
Epoch 158/200
19223/19223 [==============================] - 0s - loss: 0.7842 - acc: 0.7042     
Epoch 159/200
19223/19223 [==============================] - 0s - loss: 0.7837 - acc: 0.7012     
Epoch 160/200
19223/19223 [==============================] - 0s - loss: 0.7842 - acc: 0.7037     
Epoch 161/200
19223/19223 [==============================] - 0s - loss: 0.7887 - acc: 0.7041     - ETA: 0s - loss: 0.7762 - ac
Epoch 162/200
19223/19223 [==============================] - 0s - loss: 0.7814 - acc: 0.7050     
Epoch 163/200
19223/19223 [==============================] - 0s - loss: 0.7767 - acc: 0.7056     
Epoch 164/200
19223/19223 [==============================] - 0s - loss: 0.7811 - acc: 0.7050     
Epoch 165/200
19223/19223 [==============================] - 0s - loss: 0.7847 - acc: 0.7060     
Epoch 166/200
19223/19223 [==============================] - 0s - loss: 0.7828 - acc: 0.7025     
Epoch 167/200
19223/19223 [==============================] - 0s - loss: 0.7825 - acc: 0.7027     
Epoch 168/200
19223/19223 [==============================] - 0s - loss: 0.7768 - acc: 0.7063     
Epoch 169/200
19223/19223 [==============================] - 0s - loss: 0.7809 - acc: 0.7037     
Epoch 170/200
19223/19223 [==============================] - 0s - loss: 0.7836 - acc: 0.7021     
Epoch 171/200
19223/19223 [==============================] - 0s - loss: 0.7808 - acc: 0.7041     
Epoch 172/200
19223/19223 [==============================] - 0s - loss: 0.7832 - acc: 0.7043     
Epoch 173/200
19223/19223 [==============================] - 0s - loss: 0.7802 - acc: 0.7022     
Epoch 174/200
19223/19223 [==============================] - 0s - loss: 0.7789 - acc: 0.7025     
Epoch 175/200
19223/19223 [==============================] - 0s - loss: 0.7811 - acc: 0.7045     
Epoch 176/200
19223/19223 [==============================] - 0s - loss: 0.7817 - acc: 0.7039     
Epoch 177/200
19223/19223 [==============================] - 0s - loss: 0.7835 - acc: 0.7069     
Epoch 178/200
19223/19223 [==============================] - 0s - loss: 0.7831 - acc: 0.7018     
Epoch 179/200
19223/19223 [==============================] - 0s - loss: 0.7807 - acc: 0.7034     
Epoch 180/200
19223/19223 [==============================] - 0s - loss: 0.7772 - acc: 0.7043     
Epoch 181/200
19223/19223 [==============================] - 0s - loss: 0.7825 - acc: 0.7029     
Epoch 182/200
19223/19223 [==============================] - 0s - loss: 0.7818 - acc: 0.7032     
Epoch 183/200
19223/19223 [==============================] - 0s - loss: 0.7784 - acc: 0.7052     
Epoch 184/200
19223/19223 [==============================] - 0s - loss: 0.7826 - acc: 0.7037     
Epoch 185/200
19223/19223 [==============================] - 0s - loss: 0.7722 - acc: 0.7071     
Epoch 186/200
19223/19223 [==============================] - 0s - loss: 0.7851 - acc: 0.7019     
Epoch 187/200
19223/19223 [==============================] - 0s - loss: 0.7755 - acc: 0.7103     
Epoch 188/200
19223/19223 [==============================] - 0s - loss: 0.7779 - acc: 0.7080     
Epoch 189/200
19223/19223 [==============================] - 0s - loss: 0.7805 - acc: 0.7024     
Epoch 190/200
19223/19223 [==============================] - 0s - loss: 0.7814 - acc: 0.7096     
Epoch 191/200
19223/19223 [==============================] - 0s - loss: 0.7835 - acc: 0.7054     
Epoch 192/200
19223/19223 [==============================] - 0s - loss: 0.7822 - acc: 0.7099     
Epoch 193/200
19223/19223 [==============================] - 0s - loss: 0.7804 - acc: 0.7048     
Epoch 194/200
19223/19223 [==============================] - 0s - loss: 0.7807 - acc: 0.7035     
Epoch 195/200
19223/19223 [==============================] - 0s - loss: 0.7800 - acc: 0.7105     
Epoch 196/200
19223/19223 [==============================] - 0s - loss: 0.7706 - acc: 0.7108     
Epoch 197/200
19223/19223 [==============================] - 0s - loss: 0.7739 - acc: 0.7042     
Epoch 198/200
19223/19223 [==============================] - 0s - loss: 0.7772 - acc: 0.7081     
Epoch 199/200
19223/19223 [==============================] - 0s - loss: 0.7785 - acc: 0.7067     
Epoch 200/200
19223/19223 [==============================] - 0s - loss: 0.7720 - acc: 0.7073     
Out[856]:
<keras.callbacks.History at 0x143ce7e48>

Predicting the positions of the First NBA Team of 2017

As a first test of the model, we will predict the positions of the player in the First NBA Team of 2017


In [857]:
first_team_members = ['Russell Westbrook', 'James Harden', 'Anthony Davis', 'LeBron James', 'Kawhi Leonard']
first_team_stats = data[[((x[1]['Player'] in first_team_members) & (x[1]['Year']==2017)) for x in data.iterrows()]]
first_team_stats


Out[857]:
Year Player Pos Age G GS MP PER TS% 3PAr ... DRB TRB AST STL BLK TOV PF PTS height weight
19326 2017.0 Anthony Davis C 23.0 75.0 75.0 2708.0 0.365583 0.579 0.088 ... 9.465288 11.778434 2.087149 1.249631 2.220089 2.406204 2.233383 27.903988 206.0 97.0
19399 2017.0 James Harden PG 27.0 81.0 81.0 2947.0 0.333492 0.613 0.493 ... 6.889718 8.050221 11.067526 1.465898 0.451985 5.668137 2.626400 28.780455 196.0 99.0
19444 2017.0 LeBron James SF 32.0 74.0 74.0 2794.0 0.347888 0.619 0.254 ... 6.996421 8.246242 8.323550 1.185397 0.566929 3.904080 1.726557 25.176807 203.0 113.0
19486 2017.0 Kawhi Leonard SF 25.0 74.0 74.0 2474.0 0.400162 0.611 0.294 ... 5.092967 6.257074 3.783347 1.920776 0.800323 2.240905 1.775263 27.472918 201.0 104.0
19671 2017.0 Russell Westbrook PG 28.0 81.0 81.0 2802.0 0.393148 0.554 0.300 ... 9.340471 11.100642 10.792291 1.708779 0.398287 5.627409 2.441113 32.865096 190.0 90.0

5 rows × 51 columns


In [858]:
pd.DataFrame(index=first_team_stats.loc[:, 'Player'].values, data={'Real': first_team_stats.loc[:, 'Pos'].values,
    'Predicted':encoder.inverse_transform(model.predict(Xnorm[first_team_stats.index, :]))})


Out[858]:
Predicted Real
Anthony Davis PF C
James Harden PG PG
LeBron James PF SF
Kawhi Leonard SF SF
Russell Westbrook PG PG

The model gets right four of the five. It's even more interesting that the one that gets wrong, Anthony Davis, can play in both PF and C positions, and that in the last season, he played more as a Power Forward than as a Center, as the model predicts:

New Orleans Pelicans Depth Chart - 2016-17.

Predicting the positions of the NBA MVP

We will use now the model to predict the positions of all the NBA MVP since the creation of the award, in 1956.


In [859]:
mvp = [(1956, 'Bob Pettit'), (1957, 'Bob Cousy'), (1958, 'Bill Russell'), (1959, 'Bob Pettit'), 
(1960, 'Wilt Chamberlain'), (1961, 'Bill Russell'), (1962, 'Bill Russell'), (1963, 'Bill Russell'),
(1964, 'Oscar Robertson'), (1965, 'Bill Russell'), (1966, 'Wilt Chamberlain'), (1967, 'Wilt Chamberlain'),
(1968, 'Wilt Chamberlain'), (1969, 'Wes Unseld'), (1970, 'Willis Reed'), (1971, 'Lew Alcindor'), 
(1972, 'Kareem Abdul-Jabbar'), (1973, 'Dave Cowens'), (19704, 'Kareem Abdul-Jabbar'), (1975, 'Bob McAdoo'),
(1976, 'Kareem Abdul-Jabbar'), (1977, 'Kareem Abdul-Jabbar'), (1978, 'Bill Walton'), (1979, 'Moses Malone'), 
(1980, 'Kareem Abdul-Jabbar'), (1981, 'Julius Erving'), (1982, 'Moses Malone'), (1983, 'Moses Malone'), 
(1984, 'Larry Bird'), (1985, 'Larry Bird'), (1986, 'Larry Bird'), (1987, 'Magic Johnson'), 
(1988, 'Michael Jordan'), (1989, 'Magic Johnson'), (1990, 'Magic Johnson'), (1991, 'Michael Jordan'),
(1992, 'Michael Jordan'), (1993, 'Charles Barkley'), (1994, 'Hakeem Olajuwon'), (1995, 'David Robinson'),  
(1996, 'Michael Jordan'), (1997, 'Karl Malone'), (1998, 'Michael Jordan'), (1999, 'Karl Malone'), 
(2000, 'Shaquille O\'Neal'), (2001, 'Allen Iverson'), (2002, 'Tim Duncan'), (2003, 'Tim Duncan'), 
(2004, 'Kevin Garnett'), (2005, 'Steve Nash'), (2006, 'Steve Nash'), (2007, 'Dirk Nowitzki'), 
(2008, 'Kobe Bryant'), (2009, 'LeBron James'), (2010, 'LeBron James'), (2011, 'Derrick Rose'), 
(2012, 'LeBron James'), (2013, 'LeBron James'), (2014, 'Kevin Durant'), (2015, 'Stephen Curry'),
(2016, 'Stephen Curry')]

In [860]:
mvp_stats = pd.concat([data[(data['Player'] == x[1]) & (data['Year']==x[0])] for x in mvp], axis=0)

In [861]:
mvp_stats


Out[861]:
Year Player Pos Age G GS MP PER TS% 3PAr ... DRB TRB AST STL BLK TOV PF PTS height weight
497 1956.0 Bob Pettit C 23.0 72.0 0.0 2794.0 0.351754 0.502 0.000 ... 0.000000 14.997853 2.435218 0.000000 0.000000 0.000000 2.602720 23.823908 206.0 92.0
536 1957.0 Bob Cousy PG 28.0 64.0 0.0 2364.0 0.319797 0.452 0.000 ... 0.000000 4.705584 7.279188 0.000000 0.000000 0.000000 2.040609 20.086294 185.0 79.0
688 1958.0 Bill Russell C 23.0 69.0 0.0 2640.0 0.310909 0.465 0.000 ... 0.000000 21.327273 2.754545 0.000000 0.000000 0.000000 2.468182 15.572727 208.0 97.0
784 1959.0 Bob Pettit PF 26.0 72.0 0.0 2873.0 0.353359 0.519 0.000 ... 0.000000 14.810999 2.769231 0.000000 0.000000 0.000000 2.506091 26.376610 206.0 92.0
827 1960.0 Wilt Chamberlain C 23.0 72.0 0.0 3338.0 0.301977 0.493 0.000 ... 0.000000 20.933493 1.811863 0.000000 0.000000 0.000000 1.617735 29.194727 216.0 124.0
992 1961.0 Bill Russell C 26.0 78.0 0.0 3458.0 0.188433 0.454 0.000 ... 0.000000 19.447079 2.790052 0.000000 0.000000 0.000000 1.613650 13.762869 208.0 97.0
1095 1962.0 Bill Russell C 27.0 76.0 0.0 3433.0 0.203437 0.489 0.000 ... 0.000000 18.770754 3.575881 0.000000 0.000000 0.000000 2.170696 15.058549 208.0 97.0
1208 1963.0 Bill Russell C 28.0 78.0 0.0 3500.0 0.187200 0.464 0.000 ... 0.000000 18.956571 3.579429 0.000000 0.000000 0.000000 1.944000 13.464000 208.0 97.0
1320 1964.0 Oscar Robertson PG 25.0 79.0 0.0 3559.0 0.279180 0.576 0.000 ... 0.000000 7.920202 8.779994 0.000000 0.000000 0.000000 2.832256 25.085698 196.0 92.0
1440 1965.0 Bill Russell C 30.0 78.0 0.0 3466.0 0.202539 0.472 0.000 ... 0.000000 19.506059 4.258511 0.000000 0.000000 0.000000 2.118869 11.446047 208.0 97.0
1482 1966.0 Wilt Chamberlain C 29.0 79.0 0.0 3737.0 0.272625 0.547 0.000 ... 0.000000 18.717688 3.988226 0.000000 0.000000 0.000000 1.647311 25.518865 216.0 124.0
1589 1967.0 Wilt Chamberlain C 30.0 81.0 0.0 3682.0 0.259098 0.637 0.000 ... 0.000000 19.134166 6.159696 0.000000 0.000000 0.000000 1.398153 19.124389 216.0 124.0
1711 1968.0 Wilt Chamberlain C 31.0 82.0 0.0 3836.0 0.231804 0.557 0.000 ... 0.000000 18.319082 6.588113 0.000000 0.000000 0.000000 1.501564 18.694473 216.0 124.0
2005 1969.0 Wes Unseld C 22.0 82.0 0.0 2970.0 0.219394 0.515 0.000 ... 0.000000 18.072727 2.581818 0.000000 0.000000 0.000000 3.345455 13.709091 201.0 111.0
2148 1970.0 Willis Reed C 27.0 81.0 0.0 3089.0 0.236581 0.552 0.000 ... 0.000000 13.122693 1.876335 0.000000 0.000000 0.000000 3.344772 20.453221 206.0 106.0
2406 1972.0 Kareem Abdul-Jabbar C 24.0 81.0 0.0 3583.0 0.300419 0.603 0.000 ... 0.000000 13.523863 3.717555 0.000000 0.000000 0.000000 2.361150 28.353893 218.0 102.0
2665 1973.0 Dave Cowens C 24.0 82.0 0.0 3425.0 0.190248 0.481 0.000 ... 0.000000 13.969051 3.500146 0.000000 0.000000 0.000000 3.268905 17.700438 206.0 104.0
3195 1975.0 Bob McAdoo C 23.0 82.0 0.0 3539.0 0.262447 0.569 0.000 ... 8.626166 11.749082 1.820853 0.935858 1.769992 0.000000 2.827917 28.797966 206.0 95.0
3303 1976.0 Kareem Abdul-Jabbar C 28.0 82.0 0.0 3379.0 0.289790 0.567 0.000 ... 11.836638 14.734537 4.400118 1.267831 3.601065 0.000000 3.110980 24.237940 218.0 102.0
3536 1977.0 Kareem Abdul-Jabbar C 29.0 82.0 0.0 3016.0 0.331830 0.608 0.000 ... 9.835544 13.010610 3.807692 1.205570 3.115385 0.000000 3.127321 25.687003 218.0 102.0
4131 1978.0 Bill Walton C 25.0 58.0 0.0 1929.0 0.462830 0.554 0.000 ... 12.093313 14.295490 5.430793 1.119751 2.724728 3.844479 2.706065 20.472784 211.0 95.0
4334 1979.0 Moses Malone C 23.0 82.0 0.0 3390.0 0.251681 0.604 0.000 ... 9.100885 15.334513 1.561062 0.838938 1.263717 3.461947 2.368142 21.568142 208.0 97.0
4464 1980.0 Kareem Abdul-Jabbar C 32.0 82.0 0.0 3143.0 0.289787 0.639 0.001 ... 7.972001 10.148266 4.249443 0.927776 3.207127 3.401845 2.474069 23.297486 218.0 102.0
4854 1981.0 Julius Erving SF 30.0 82.0 0.0 2874.0 0.314405 0.572 0.012 ... 5.173278 8.229645 4.559499 2.167015 1.841336 3.331942 2.918580 25.227557 201.0 95.0
5271 1982.0 Moses Malone C 26.0 81.0 81.0 3398.0 0.283932 0.576 0.003 ... 6.674514 12.586227 1.504414 0.805180 1.324308 3.114773 2.203649 26.698058 208.0 97.0
5595 1983.0 Moses Malone C 27.0 78.0 78.0 2922.0 0.309240 0.578 0.001 ... 9.227926 14.710472 1.244353 1.096509 1.934292 3.252567 2.537988 23.507187 208.0 97.0
5750 1984.0 Larry Bird PF 27.0 79.0 77.0 3028.0 0.287715 0.552 0.047 ... 7.311757 9.463672 6.182299 1.712021 0.820343 2.817701 2.342140 22.684280 206.0 99.0
6042 1985.0 Larry Bird SF 28.0 80.0 77.0 3161.0 0.301803 0.585 0.074 ... 7.721607 9.589370 6.047453 1.469155 1.116102 2.824423 2.368871 26.137298 206.0 99.0
6339 1986.0 Larry Bird SF 29.0 82.0 81.0 3113.0 0.296049 0.580 0.121 ... 7.112111 9.309348 6.441375 1.919692 0.589785 3.076132 2.104722 24.458721 206.0 99.0
6761 1987.0 Magic Johnson PG 27.0 80.0 80.0 2904.0 0.334711 0.602 0.030 ... 4.735537 6.247934 12.111570 1.710744 0.446281 3.719008 2.082645 23.665289 201.0 98.0
7103 1988.0 Michael Jordan SG 24.0 82.0 82.0 3311.0 0.344669 0.603 0.027 ... 3.370583 4.881909 5.273331 2.816068 1.424343 2.739958 2.935669 31.183328 198.0 88.0
7435 1989.0 Magic Johnson PG 29.0 77.0 77.0 2886.0 0.335551 0.625 0.165 ... 6.187110 7.571726 12.324324 1.721414 0.274428 3.891892 2.145530 21.580042 201.0 98.0
7807 1990.0 Magic Johnson PG 30.0 79.0 79.0 2937.0 0.326047 0.622 0.243 ... 4.829418 6.398366 11.117467 1.617978 0.416752 3.542390 2.046987 21.634321 201.0 98.0
8181 1991.0 Michael Jordan SG 27.0 82.0 82.0 3034.0 0.374951 0.605 0.051 ... 4.437706 5.837838 5.375082 2.646012 0.984838 2.396836 2.717205 30.613052 198.0 88.0
8547 1992.0 Michael Jordan SG 28.0 80.0 80.0 3102.0 0.321470 0.579 0.055 ... 4.874275 5.930368 5.675048 2.112186 0.870406 2.321083 2.332689 27.899420 198.0 88.0
8754 1993.0 Charles Barkley PF 29.0 76.0 76.0 2859.0 0.326128 0.596 0.160 ... 8.700944 11.685205 4.847849 1.498426 0.931794 2.933893 2.467996 24.478489 198.0 114.0
9333 1994.0 Hakeem Olajuwon C 31.0 80.0 80.0 3277.0 0.277937 0.565 0.011 ... 7.975587 10.491303 3.152884 1.406164 3.262740 2.977113 3.174855 23.992676 213.0 115.0
9738 1995.0 David Robinson C 29.0 81.0 81.0 3074.0 0.340794 0.602 0.013 ... 7.530254 10.270657 2.763826 1.569291 3.068315 2.728692 2.693559 26.209499 216.0 106.0
10020 1996.0 Michael Jordan SG 32.0 82.0 82.0 3090.0 0.342524 0.582 0.141 ... 4.601942 6.326214 4.100971 2.097087 0.489320 2.295146 2.271845 29.021359 198.0 88.0
10499 1997.0 Karl Malone PF 33.0 82.0 82.0 2998.0 0.347031 0.600 0.008 ... 7.396931 9.714476 4.418946 1.356905 0.576384 2.797865 2.605737 27.006004 206.0 113.0
10910 1998.0 Michael Jordan SG 34.0 82.0 82.0 3181.0 0.285193 0.533 0.067 ... 3.904433 5.375668 3.202766 1.595725 0.509274 2.093681 1.708897 26.674631 198.0 88.0
11352 1999.0 Karl Malone PF 35.0 49.0 49.0 1832.0 0.503057 0.577 0.001 ... 6.995633 9.098253 3.949782 1.218341 0.550218 3.183406 2.633188 22.873362 206.0 113.0
11793 2000.0 Shaquille O'Neal C 27.0 79.0 79.0 3163.0 0.348277 0.578 0.001 ... 8.445147 12.269365 3.403098 0.409738 2.720202 2.538097 2.902308 26.678470 216.0 147.0
12093 2001.0 Allen Iverson SG 25.0 71.0 71.0 2979.0 0.290030 0.518 0.169 ... 2.694864 3.299094 3.927492 2.151057 0.241692 2.864048 1.776435 26.670695 183.0 74.0
12459 2002.0 Tim Duncan PF 25.0 82.0 82.0 3329.0 0.291980 0.576 0.007 ... 8.370081 11.268249 3.319916 0.659658 2.195254 2.844097 2.346651 22.590568 211.0 113.0
12849 2003.0 Tim Duncan PF 26.0 81.0 81.0 3181.0 0.304433 0.564 0.016 ... 8.872682 11.803835 3.576234 0.622446 2.682175 2.806665 2.614272 21.321597 211.0 113.0
13287 2004.0 Kevin Garnett PF 27.0 82.0 82.0 3231.0 0.327577 0.547 0.027 ... 9.961003 12.690808 4.557103 1.337047 1.983287 2.362117 2.250696 22.139276 211.0 108.0
13921 2005.0 Steve Nash PG 30.0 75.0 75.0 2573.0 0.307812 0.606 0.254 ... 2.686358 3.483871 12.046638 1.035367 0.083949 3.427905 1.902837 16.300039 190.0 88.0
14378 2006.0 Steve Nash PG 31.0 79.0 79.0 2796.0 0.300000 0.632 0.324 ... 3.682403 4.287554 10.635193 0.785408 0.154506 3.553648 1.545064 19.171674 190.0 88.0
14825 2007.0 Dirk Nowitzki PF 28.0 78.0 78.0 2820.0 0.352340 0.605 0.129 ... 7.289362 8.846809 3.357447 0.663830 0.791489 2.131915 2.182979 24.459574 213.0 111.0
15027 2008.0 Kobe Bryant SG 29.0 82.0 82.0 3192.0 0.272932 0.576 0.246 ... 4.770677 5.830827 4.973684 1.703008 0.451128 2.898496 2.560150 26.199248 198.0 96.0
15642 2009.0 LeBron James SF 24.0 81.0 81.0 3054.0 0.373674 0.591 0.238 ... 5.976424 7.225933 6.919450 1.614931 1.096267 2.840864 1.638507 27.159136 203.0 113.0
16109 2010.0 LeBron James SF 25.0 76.0 76.0 2966.0 0.377478 0.604 0.253 ... 5.862441 6.724208 7.901551 1.517195 0.934592 3.167903 1.444370 27.406608 203.0 113.0
16745 2011.0 Derrick Rose PG 22.0 81.0 81.0 3026.0 0.279577 0.550 0.241 ... 2.962327 3.925975 7.411765 1.011236 0.606742 3.307336 1.617978 24.103106 190.0 86.0
17060 2012.0 LeBron James SF 27.0 62.0 62.0 2326.0 0.475150 0.605 0.127 ... 6.159931 7.614789 5.989682 1.779880 0.773861 3.296647 1.485813 26.048151 203.0 113.0
17499 2013.0 LeBron James PF 28.0 76.0 76.0 2877.0 0.395412 0.640 0.188 ... 6.419187 7.632951 6.894682 1.614181 0.838373 2.827946 1.376434 25.476538 203.0 113.0
17897 2014.0 Kevin Durant SF 25.0 81.0 81.0 3122.0 0.343626 0.635 0.291 ... 6.226778 6.895580 5.131326 1.187700 0.680333 3.286355 2.006406 29.900064 206.0 108.0
18344 2015.0 Stephen Curry PG 26.0 80.0 80.0 2613.0 0.385763 0.638 0.482 ... 3.926521 4.698048 8.528129 2.245695 0.220436 3.430540 2.176808 26.176808 190.0 86.0
18842 2016.0 Stephen Curry PG 27.0 79.0 79.0 2700.0 0.420000 0.669 0.554 ... 4.826667 5.733333 7.026667 2.253333 0.200000 3.493333 2.146667 31.666667 190.0 86.0

59 rows × 51 columns


In [862]:
mvp_pred = pd.DataFrame(index=mvp_stats.loc[:, 'Player'].values, data={'Real': mvp_stats.loc[:, 'Pos'].values,
    'Predicted':encoder.inverse_transform(model.predict(Xnorm[mvp_stats.index, :]))})

In [737]:
mvp_pred


Out[737]:
Predicted Real
Bob Pettit C C
Bob Cousy PG PG
Bill Russell C C
Bob Pettit C PF
Wilt Chamberlain C C
Bill Russell C C
Bill Russell C C
Bill Russell C C
Oscar Robertson SG PG
Bill Russell C C
Wilt Chamberlain C C
Wilt Chamberlain C C
Wilt Chamberlain C C
Wes Unseld C C
Willis Reed C C
Kareem Abdul-Jabbar C C
Dave Cowens C C
Bob McAdoo C C
Kareem Abdul-Jabbar C C
Kareem Abdul-Jabbar C C
Bill Walton C C
Moses Malone C C
Kareem Abdul-Jabbar C C
Julius Erving SF SF
Moses Malone PF C
Moses Malone C C
Larry Bird PF PF
Larry Bird PF SF
Larry Bird SF SF
Magic Johnson PG PG
Michael Jordan SG SG
Magic Johnson PG PG
Magic Johnson PG PG
Michael Jordan SG SG
Michael Jordan SG SG
Charles Barkley PF PF
Hakeem Olajuwon C C
David Robinson C C
Michael Jordan SG SG
Karl Malone PF PF
Michael Jordan SG SG
Karl Malone PF PF
Shaquille O'Neal C C
Allen Iverson PG SG
Tim Duncan C PF
Tim Duncan C PF
Kevin Garnett C PF
Steve Nash PG PG
Steve Nash PG PG
Dirk Nowitzki C PF
Kobe Bryant SG SG
LeBron James SF SF
LeBron James SG SF
Derrick Rose PG PG
LeBron James SF SF
LeBron James SF PF
Kevin Durant SF SF
Stephen Curry PG PG
Stephen Curry PG PG

The model gets right most of the players, and the errors are always for a contiguous position (it is interesting that the model gets this right without having been provided with any information about the distances between the labels.)

Does year metter?

The definitions of a forward or a center are always changing: in the very recent years, there is, for example, a trend towards having scoring point guards (as Stephen Curry) and forwards that direct the game instead of the guard (as Lebron James). Also, the physical requirements are increasing, and a height that in the 50's could characterize you as a center will make you a forward today.

We will follow the first and last MVP's, Stephen Curry and Bob Pettit, and see where our model puts them in different years in the NBA history.


In [863]:
curry2017 = data[(data['Player'] == 'Stephen Curry') & (data['Year']==2017)] 
pettit1956 = data[(data['Player'] == 'Bob Pettit') & (data['Year']==1956)]

In [864]:
time_travel_curry = pd.concat([curry2017 for year in range(1956, 2018)], axis=0)
time_travel_curry['Year'] = range(1956, 2018)

X = time_travel_curry.drop(['Player', 'Pos', 'G', 'GS', 'MP'], axis=1).as_matrix()
y = time_travel_curry['Pos'].as_matrix()

y_cat = encoder.transform(y)
Xnorm = scaler.transform(X)

time_travel_curry_pred = pd.DataFrame(index=time_travel_curry.loc[:, 'Year'].values, 
                                data={'Real': time_travel_curry.loc[:, 'Pos'].values,
    'Predicted':encoder.inverse_transform(model.predict(Xnorm))})


time_travel_pettit = pd.concat([pettit1956 for year in range(1956, 2018)], axis=0)
time_travel_pettit['Year'] = range(1956, 2018)

X = time_travel_pettit.drop(['Player', 'Pos', 'G', 'GS', 'MP'], axis=1).as_matrix()
y = time_travel_pettit['Pos'].as_matrix()

y_cat = encoder.transform(y)
Xnorm = scaler.transform(X)

time_travel_pettit_pred = pd.DataFrame(index=time_travel_pettit.loc[:, 'Year'].values, 
                                data={'Real': time_travel_pettit.loc[:, 'Pos'].values,
    'Predicted':encoder.inverse_transform(model.predict(Xnorm))})

In [865]:
pd.concat([time_travel_curry_pred,time_travel_pettit_pred],axis=1,keys=['Stephen Curry','Bob Pettit'])


Out[865]:
Stephen Curry Bob Pettit
Predicted Real Predicted Real
1956 SG PG C C
1957 SG PG C C
1958 SG PG C C
1959 SG PG C C
1960 SG PG C C
1961 SG PG C C
1962 SG PG C C
1963 SG PG C C
1964 SG PG C C
1965 SG PG C C
1966 SG PG C C
1967 SG PG C C
1968 SG PG PF C
1969 SG PG PF C
1970 SG PG PF C
1971 SG PG PF C
1972 SG PG PF C
1973 PG PG PF C
1974 PG PG PF C
1975 PG PG PF C
1976 PG PG PF C
1977 PG PG PF C
1978 PG PG PF C
1979 PG PG PF C
1980 PG PG PF C
1981 PG PG PF C
1982 PG PG PF C
1983 PG PG PF C
1984 PG PG PF C
1985 PG PG PF C
... ... ... ... ...
1988 PG PG PF C
1989 PG PG PF C
1990 PG PG PF C
1991 PG PG PF C
1992 PG PG PF C
1993 PG PG PF C
1994 PG PG PF C
1995 PG PG PF C
1996 PG PG PF C
1997 PG PG PF C
1998 PG PG PF C
1999 PG PG PF C
2000 PG PG PF C
2001 PG PG PF C
2002 PG PG PF C
2003 PG PG PF C
2004 PG PG PF C
2005 PG PG PF C
2006 PG PG PF C
2007 PG PG PF C
2008 PG PG PF C
2009 PG PG PF C
2010 PG PG PF C
2011 PG PG PF C
2012 PG PG PF C
2013 PG PG PF C
2014 PG PG PF C
2015 PG PG PF C
2016 PG PG PF C
2017 PG PG PF C

62 rows × 4 columns

Curry is labeled as a point guard (his real position) from 1973 until today, and as a shooting guard before that. Perhaps because of his heigh (191cm), or perhaps because he is too much of a scorer. Bob Pettit is labeled as a center until 1967, and as a power forward after that (he played both roles, but nowadays he would have difficulties to play as a center, and would be for sure a forward, perhaps even a small forward).

Changing positions

Many players go towards more interior roles with age, as they lose velocity. We will follow two cases, Magic Johnson, and Michael Jordan. Both of them retired, and returned years later with more interior roles.


In [866]:
magic = data[(data['Player'] == 'Magic Johnson')] 
jordan = data[(data['Player'] == 'Michael Jordan')]

In [867]:
# Magic
X = magic.drop(['Player', 'Pos', 'G', 'GS', 'MP'], axis=1).as_matrix()
y = magic['Pos'].as_matrix()

y_cat = encoder.transform(y)
Xnorm = scaler.transform(X)

magic_pred = pd.DataFrame(index=magic.loc[:, 'Age'].values, 
                                data={'Real': magic.loc[:, 'Pos'].values,
    'Predicted':encoder.inverse_transform(model.predict(Xnorm))})

# Jordan
X = jordan.drop(['Player', 'Pos', 'G', 'GS', 'MP'], axis=1).as_matrix()
y = jordan['Pos'].as_matrix()

y_cat = encoder.transform(y)
Xnorm = scaler.transform(X)

jordan_pred = pd.DataFrame(index=jordan.loc[:, 'Age'].values, 
                                data={'Real': jordan.loc[:, 'Pos'].values,
    'Predicted':encoder.inverse_transform(model.predict(Xnorm))})

In [869]:
pd.concat([magic_pred,jordan_pred],axis=1,keys=['Magic Johnson','Michael Jordan'])


Out[869]:
Magic Johnson Michael Jordan
Predicted Real Predicted Real
20.0 SF SG NaN NaN
21.0 SG SG SG SG
22.0 SG SG SG SG
23.0 PG SG SG SG
24.0 PG PG SG SG
25.0 PG PG SG SG
26.0 PG PG SG SG
27.0 PG PG SG SG
28.0 PG PG SG SG
29.0 PG PG SG SG
30.0 PG PG NaN NaN
31.0 PG PG SG SG
32.0 NaN NaN SG SG
33.0 NaN NaN SG SG
34.0 NaN NaN SG SG
36.0 SG PF NaN NaN
38.0 NaN NaN SF SF
39.0 NaN NaN SF SF

The model is able to detect the conversion of Jordan into a forward at the end of his career, but not the return of Magic as a power forward. Also, in his rookie season, he is classified as a small forward instead of as a shooting guard (Magic was clearly and outlier in the data, a 205cm point guard who could easily play in the five positions. It is even surprising that is properly labelled as a point guard during most of his career)

How important are height and weight?

A concern we have before training the model was that it would use the height and weight as the main classifiers, and that it would label incorrectly players as Magic Johnson (a 205 cm point guard), or Charles Barkley (a 196cm power forward). Almost surprisingly, it works properly on this two players.

We will use again the 2017 First NBA Team and play with the heights and weights of the players. Keeping constant all other statistics, we will change the height and weight and observe how the predicted positions change.


In [1]:
first_team_stats


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-0f3bd6776171> in <module>()
----> 1 first_team_stats

NameError: name 'first_team_stats' is not defined

In [871]:
multiplier = np.arange(0.8,1.2,0.02)
growing_predicted = []

for p in first_team_stats.iterrows():
    growing = pd.concat([p[1].to_frame().T for x in multiplier], axis=0)
    growing['height'] = growing['height'] * multiplier
    growing['weight'] = growing['weight'] * (multiplier ** 3)

    X = growing.drop(['Player', 'Pos', 'G', 'GS', 'MP'], axis=1).as_matrix()
    y = growing['Pos'].as_matrix()

    y_cat = encoder.transform(y)
    Xnorm = scaler.transform(X)

    growing_predicted.append(pd.DataFrame(index=multiplier, data={'height': growing.loc[:, 'height'].values,
            'Real': growing.loc[:, 'Pos'].values, 'Predicted':encoder.inverse_transform(model.predict(Xnorm))}))


/usr/local/lib/python3.6/site-packages/sklearn/utils/validation.py:429: DataConversionWarning: Data with input dtype object was converted to float64 by StandardScaler.
  warnings.warn(msg, _DataConversionWarning)

In [874]:
pd.concat(growing_predicted,axis=1,keys=first_team_stats['Player'])


Out[874]:
Player Anthony Davis James Harden LeBron James Kawhi Leonard Russell Westbrook
Predicted Real height Predicted Real height Predicted Real height Predicted Real height Predicted Real height
0.80 PF C 164.8 PG PG 156.8 PG SF 162.4 PG SF 160.8 PG PG 152
0.82 PF C 168.92 PG PG 160.72 PG SF 166.46 PG SF 164.82 PG PG 155.8
0.84 PF C 173.04 PG PG 164.64 PG SF 170.52 PG SF 168.84 PG PG 159.6
0.86 PF C 177.16 PG PG 168.56 PG SF 174.58 PG SF 172.86 PG PG 163.4
0.88 PF C 181.28 PG PG 172.48 PG SF 178.64 PG SF 176.88 PG PG 167.2
0.90 PF C 185.4 PG PG 176.4 PG SF 182.7 SG SF 180.9 PG PG 171
0.92 PF C 189.52 PG PG 180.32 PG SF 186.76 SG SF 184.92 PG PG 174.8
0.94 PF C 193.64 PG PG 184.24 PG SF 190.82 SG SF 188.94 PG PG 178.6
0.96 PF C 197.76 PG PG 188.16 SF SF 194.88 SG SF 192.96 PG PG 182.4
0.98 PF C 201.88 PG PG 192.08 SF SF 198.94 SG SF 196.98 PG PG 186.2
1.00 PF C 206 PG PG 196 PF SF 203 SF SF 201 PG PG 190
1.02 PF C 210.12 PG PG 199.92 PF SF 207.06 SF SF 205.02 PG PG 193.8
1.04 C C 214.24 PG PG 203.84 C SF 211.12 SF SF 209.04 SF PG 197.6
1.06 C C 218.36 PG PG 207.76 C SF 215.18 PF SF 213.06 PF PG 201.4
1.08 C C 222.48 PF PG 211.68 C SF 219.24 PF SF 217.08 PF PG 205.2
1.10 C C 226.6 C PG 215.6 C SF 223.3 C SF 221.1 PF PG 209
1.12 C C 230.72 C PG 219.52 C SF 227.36 C SF 225.12 PF PG 212.8
1.14 C C 234.84 C PG 223.44 C SF 231.42 C SF 229.14 C PG 216.6
1.16 C C 238.96 C PG 227.36 C SF 235.48 C SF 233.16 C PG 220.4
1.18 C C 243.08 C PG 231.28 C SF 239.54 C SF 237.18 C PG 224.2

As we can see height matters, but it's not enough. Any player can be classified as a center if he is tall enough (very tall: Kawhi Leonard would need to be 221cm tall to be considered a center), but being short it's not enough to be considered a guard: a 165cm Anthony Davis would be still considered a power forward.


In [ ]: