├── nn
├── __init__.py
├── td_prediction_lstm_V3.py
├── td_prediction_lstm_V4.py
└── td_two_tower_lstm.py
├── .gitignore
├── infos
├── IJCAI18_poster.pdf
├── IceHockey-IJCAI2018-Presentation.pdf
└── BibTex.bib
├── images
└── DP-lstm-model-structure.png
├── .idea
├── libraries
│ └── R_User_Library.xml
├── misc.xml
├── vcs.xml
├── modules.xml
├── DRL-ice-hockey.iml
└── workspace.xml
├── configuration.py
├── LICENSE
├── README.md
├── utils.py
├── td_three_prediction_lstm.py
└── bak
└── player_ranking_match_by_match_td_lstm.py
/nn/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | .idea
3 | models/
4 |
--------------------------------------------------------------------------------
/infos/IJCAI18_poster.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guiliang/DRL-ice-hockey/HEAD/infos/IJCAI18_poster.pdf
--------------------------------------------------------------------------------
/images/DP-lstm-model-structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guiliang/DRL-ice-hockey/HEAD/images/DP-lstm-model-structure.png
--------------------------------------------------------------------------------
/infos/IceHockey-IJCAI2018-Presentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guiliang/DRL-ice-hockey/HEAD/infos/IceHockey-IJCAI2018-Presentation.pdf
--------------------------------------------------------------------------------
/.idea/libraries/R_User_Library.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/configuration.py:
--------------------------------------------------------------------------------
1 | MODEL_TYPE = "v4"
2 | MAX_TRACE_LENGTH = 2
3 | FEATURE_NUMBER = 25
4 | BATCH_SIZE = 32
5 | GAMMA = 1
6 | H_SIZE = 512
7 | USE_HIDDEN_STATE = False
8 | model_train_continue = True
9 | SCALE = True
10 | FEATURE_TYPE = 5
11 | ITERATE_NUM = 30
12 | learning_rate = 1e-4
13 | SPORT = "NHL"
14 | save_mother_dir = "/Local-Scratch"
--------------------------------------------------------------------------------
/.idea/DRL-ice-hockey.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/infos/BibTex.bib:
--------------------------------------------------------------------------------
1 | @inproceedings{ijcai2018-478,
2 | title = {Deep Reinforcement Learning in Ice Hockey for Context-Aware Player Evaluation},
3 | author = {Guiliang Liu and Oliver Schulte},
4 | booktitle = {Proceedings of the Twenty-Seventh International Joint Conference on
5 | Artificial Intelligence, {IJCAI-18}},
6 | publisher = {International Joint Conferences on Artificial Intelligence Organization},
7 | pages = {3442--3448},
8 | year = {2018},
9 | month = {7},
10 | doi = {10.24963/ijcai.2018/478},
11 | url = {https://doi.org/10.24963/ijcai.2018/478},
12 | }
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Guiliang Liu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/nn/td_prediction_lstm_V3.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 |
4 | class td_prediction_lstm_V3:
5 | def __init__(self, FEATURE_NUMBER, H_SIZE, MAX_TRACE_LENGTH, learning_rate, rnn_type='bp_last_step'):
6 | """
7 | define a shallow dynamic LSTM
8 | """
9 | with tf.name_scope("LSTM_layer"):
10 | self.rnn_input = tf.placeholder(tf.float32, [None, 10, FEATURE_NUMBER], name="x_1")
11 | self.trace_lengths = tf.placeholder(tf.int32, [None], name="tl")
12 |
13 | self.lstm_cell = tf.contrib.rnn.LSTMCell(num_units=H_SIZE, state_is_tuple=True,
14 | initializer=tf.random_uniform_initializer(-0.05, 0.05))
15 |
16 | self.rnn_output, self.rnn_state = tf.nn.dynamic_rnn( # while loop dynamic learning rnn
17 | inputs=self.rnn_input, cell=self.lstm_cell, sequence_length=self.trace_lengths, dtype=tf.float32,
18 | scope=rnn_type + '_rnn')
19 |
20 | # [batch_size, max_time, cell.output_size]
21 | self.outputs = tf.stack(self.rnn_output)
22 |
23 | # Hack to build the indexing and retrieve the right output.
24 | self.batch_size = tf.shape(self.outputs)[0]
25 | # Start indices for each sample
26 | self.index = tf.range(0, self.batch_size) * MAX_TRACE_LENGTH + (self.trace_lengths - 1)
27 | # Indexing
28 | self.rnn_last = tf.gather(tf.reshape(self.outputs, [-1, H_SIZE]), self.index)
29 |
30 | num_layer_1 = H_SIZE
31 | num_layer_2 = 3
32 |
33 | with tf.name_scope("Dense_Layer_first"):
34 | self.W1 = tf.get_variable('w1_xaiver', [num_layer_1, num_layer_2],
35 | initializer=tf.contrib.layers.xavier_initializer())
36 | self.b1 = tf.Variable(tf.zeros([num_layer_2]), name="b_1")
37 | self.read_out = tf.matmul(self.rnn_last, self.W1) + self.b1
38 | # self.activation1 = tf.nn.relu(self.y1, name='activation')
39 |
40 | self.y = tf.placeholder("float", [None, num_layer_2])
41 |
42 | with tf.name_scope("cost"):
43 | self.readout_action = self.read_out
44 | self.cost = tf.reduce_mean(tf.square(self.y - self.readout_action))
45 | self.diff = tf.reduce_mean(tf.abs(self.y - self.readout_action))
46 | tf.summary.histogram('cost', self.cost)
47 |
48 | with tf.name_scope("train"):
49 | self.train_step = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.cost)
50 |
--------------------------------------------------------------------------------
/nn/td_prediction_lstm_V4.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 |
4 | class td_prediction_lstm_V4:
5 | def __init__(self, FEATURE_NUMBER, H_SIZE, MAX_TRACE_LENGTH, learning_rate, rnn_type='bp_last_step'):
6 | """
7 | define a dynamic LSTM
8 | """
9 | with tf.name_scope("LSTM_layer"):
10 | self.rnn_input = tf.placeholder(tf.float32, [None, 10, FEATURE_NUMBER], name="x_1")
11 | self.trace_lengths = tf.placeholder(tf.int32, [None], name="tl")
12 |
13 | self.lstm_cell = tf.contrib.rnn.LSTMCell(num_units=H_SIZE * 2, state_is_tuple=True,
14 | initializer=tf.random_uniform_initializer(-0.05, 0.05))
15 |
16 | self.rnn_output, self.rnn_state = tf.nn.dynamic_rnn( # while loop dynamic learning rnn
17 | inputs=self.rnn_input, cell=self.lstm_cell, sequence_length=self.trace_lengths, dtype=tf.float32,
18 | scope=rnn_type + '_rnn')
19 |
20 | # [batch_size, max_time, cell.output_size]
21 | self.outputs = tf.stack(self.rnn_output)
22 |
23 | # Hack to build the indexing and retrieve the right output.
24 | self.batch_size = tf.shape(self.outputs)[0]
25 | # Start indices for each sample
26 | self.index = tf.range(0, self.batch_size) * MAX_TRACE_LENGTH + (self.trace_lengths - 1)
27 | # Indexing
28 | self.rnn_last = tf.gather(tf.reshape(self.outputs, [-1, H_SIZE * 2]), self.index)
29 |
30 | num_layer_1 = H_SIZE * 2
31 | num_layer_2 = 1000
32 | num_layer_3 = 3
33 |
34 | with tf.name_scope("Dense_Layer_first"):
35 | self.W1 = tf.get_variable('w1_xaiver', [num_layer_1, num_layer_2],
36 | initializer=tf.contrib.layers.xavier_initializer())
37 | self.b1 = tf.Variable(tf.zeros([num_layer_2]), name="b_1")
38 | self.y1 = tf.matmul(self.rnn_last, self.W1) + self.b1
39 | self.activation1 = tf.nn.relu(self.y1, name='activation')
40 |
41 | with tf.name_scope("Dense_Layer_second"):
42 | self.W2 = tf.get_variable('w2_xaiver', [num_layer_2, num_layer_3],
43 | initializer=tf.contrib.layers.xavier_initializer())
44 | self.b2 = tf.Variable(tf.zeros([num_layer_3]), name="b_2")
45 | self.read_out = tf.matmul(self.activation1, self.W2) + self.b2
46 | # self.activation1 = tf.nn.relu(self.y1, name='activation')
47 |
48 | self.y = tf.placeholder("float", [None, num_layer_3])
49 |
50 | with tf.name_scope("cost"):
51 | self.readout_action = self.read_out
52 | self.cost = tf.reduce_mean(tf.square(self.y - self.readout_action))
53 | self.diff = tf.reduce_mean(tf.abs(self.y - self.readout_action))
54 | tf.summary.histogram('cost', self.cost)
55 |
56 | with tf.name_scope("train"):
57 | self.train_step = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.cost)
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DRL-ice-hockey
2 |
3 | The repository contains the codes about the network structure of paper "[Deep Reinforcement Learning in Ice Hockey
4 | for Context-Aware Player Evaluation](https://www.ijcai.org/proceedings/2018/0478.pdf)".
5 |
6 | ## Network Structure:
7 |
8 | | name | nodes | activation function |
9 | | ------------- |:-------------:| -----:|
10 | | LSTM Layer | 512 | N/A |
11 | | Fully Connected Layer 1| 1024 | Relu |
12 | | Fully Connected Layer 2| 1000 | Relu |
13 | | Fully Connected Layer 3| 3 | N/A |
14 |
15 | ## Image of network structure:
16 |
17 |
18 |
19 |
20 |
21 | ## Training method
22 | We are using the on-policy prediction method [Sarsa](https://en.wikipedia.org/wiki/State%E2%80%93action%E2%80%93reward%E2%80%93state%E2%80%93action) (State–Action–Reward–State–Action).
23 | It's a Temporal Difference learning method, and estimate the player performance by Q(s,a), where state s is a series of game contexts and action a is the motion of player.
24 |
25 | ## Running:
26 | Use ```python td_three_prediction_lstm.py``` to train the neural network, which produce the Q values. Goal-Impact-Metric is the different between consecutive Q values.
27 | The origin works uses a private play-by-play dataset from [Sportlogiq](http://sportlogiq.com/en/), which we are not allowed to publish.
28 |
29 | ### About the input:
30 | If you want to run the network, please prepare your won sequential dataset, please organize the data according to network input in the format of Numpy. As it's shown in ```td_three_prediction_lstm.py```, the neural network requires three input files:
31 |
32 | * reward
33 | * state_input (conrtains both state features and one hot represetation of action)
34 | * state_trace_length
35 |
36 | To be specific, if you want to directly run this python RNN scripy, you need to prepare the input in this way. In each game file, there are three .mat files representing reward, state_input and state_trace_length. The name of files should follow the rules below:
37 |
38 | - **GameDirectory_xxx**
39 | - *dynamic_rnn_reward_xxx.mat*
40 | - A two dimensional array named 'dynamic_rnn_reward' should be in the .mat file
41 | - Row of the array: _R_, Column of the array: 10
42 | - *dynamic_rnn_input_xxx.mat*
43 | - A three dimensional array named 'dynamic_feature_input' should be in the .mat file
44 | - First dimension: _R_, Second dimension: 10, Third dimension: _feature number_
45 | - *hybrid_trace_length_xxx.mat*
46 | - A two dimensional array named 'hybrid_trace_length' should be in the .mat file
47 | - Row of the array: 1, Column of the array: Unknown
48 | - The array gives us information about how to split the length of different plays, so the sum(_array_element_) should be _R_
49 |
50 | in which *xxx* is a random string.
51 |
52 | Each input file must has the same number of rows _R_ (corresponding to number of events in a game). In our paper, we have trace length equals to 10, so reward is an _R_\*10 array, state_input is an _R_\*10\*_feature_number_ array and state_trace_length is an one demensional vector that tells the length of plays in a game.
53 |
54 | #### Examples
55 | ```
56 | # R=3, feature number=1
57 | >>> reward['dynamic_rnn_reward']
58 | array([[0, 0, 0, 1, 0, 0, 1, 0, 0, 0],
59 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
60 | [0, 0, 0, 0, 1, 0, 0, 0, 0, 0]])
61 | >>> state_input['dynamic_feature_input']
62 | array([[[-4.51194112e-02],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],
63 | [ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00]],
64 | [[-4.51194112e-02],[ 5.43495586e-04],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],
65 | [ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00]],
66 | [[-4.51194112e-02],[ 5.43495586e-04],[-3.46831161e-01],[ 0.00000000e+00],[ 0.00000000e+00],
67 | [ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00],[ 0.00000000e+00]]])
68 | >>> trace_length['hybrid_trace_length']
69 | array([[1, 2]])
70 | ```
71 |
72 | The data must be ***standardized or normalized*** before inputing to the neural network, we are using the ***sklearn.preprocessing.scale***
73 |
74 | ## Package required:
75 | Python 2.7
76 | 1. Numpy
77 | 2. Tensorflow (1.0.0?)
78 | 3. Scipy
79 | 4. Matplotlib
80 | 5. scikit-learn
81 | (We may need a requirement.txt)
82 |
83 | ## Command:
84 | (For Oliver's students with access to the net drive, the following steps should work on lab's machine)
85 |
86 | Training:
87 | 1. modify the `save_mother_dir` in `configuration.py` as your save directory, e.g. `/cs/oschulte/Bill/` or just `/local_scratch/`
88 | 2. `cd` into your `save_mother_dir`, make two directories `./models/hybrid_sl_saved_NN/` and `./models/hybrid_sl_log_NN/`
89 | 3. modify the global `DATA_STORE` variable in `td_three_prediction_lstm.py` as `/cs/oschulte/Galen/Hockey-data-entire/Hybrid-RNN-Hockey-Training-All-feature5-scale-neg_reward_v_correct__length-dynamic/`
90 | 4. check the package and python version as mentioned above
91 | 5. `python td_three_prediction_lstm.py`
92 |
93 | Evaluation:
94 | 1. suppose you have finish the step 1-5 in the training process, to evalute the network only, just disable the AdamOptimizer. Modify line 188-192 in `td_three_prediction_lstm.py` as below
95 | ```
96 | [diff, read_out, cost_out, summary_train] = sess.run(
97 | [model.diff, model.read_out, model.cost, merge],
98 | feed_dict={model.y: y_batch,
99 | model.trace_lengths: trace_t0_batch,
100 | model.rnn_input: s_t0_batch})
101 | ```
102 | 2. `python td_three_prediction_lstm.py`
103 | 3. we have a pretrained network in `/cs/oschulte/Bill/hybrid_sl_saved_NN/Scale-three-cut_together_saved_networks_feature5_batch32_iterate30_lr0.0001_v4_v_correct__MaxTL2/` only for LSTM_V4. If you want to directly use this network to evaluate, finish the step 1-4 in the training process, and modify the global `SAVED_NETWORK` variable in `td_three_prediction_lstm.py` as the previous network directory, then you can run the code using step 2.
104 |
105 |
106 | ## LICENSE:
107 | MIT LICENSE
108 |
109 | we are still updating this repository.
110 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from configuration import FEATURE_NUMBER
3 |
4 |
5 | def handle_trace_length(state_trace_length):
6 | """
7 | transform format of trace length
8 | :return:
9 | """
10 | trace_length_record = []
11 | for length in state_trace_length:
12 | for sub_length in range(0, int(length)):
13 | trace_length_record.append(sub_length + 1)
14 |
15 | return trace_length_record
16 |
17 |
18 | def get_together_training_batch(s_t0, state_input, reward, train_number, train_len, state_trace_length, BATCH_SIZE):
19 | """
20 | we generate the training batch, your can write your own method.
21 | in our dataset, 1 means home score, -1 means away score, we transfer it to one-hot representation:
22 | reward = [If_home_score, If_away_score, If_NeitherTeam_score]
23 | :return:
24 | batch_return is [s,s',r,s_play_length,s'_play_length, if_game_end, if_score_in_the_last_time_step]
25 | train_number is the current where we stop training
26 | s_t0 is the s for the next batch
27 | """
28 | batch_return = []
29 | current_batch_length = 0
30 | while current_batch_length < BATCH_SIZE:
31 | s_t1 = state_input[train_number]
32 | if len(s_t1) < 10 or len(s_t0) < 10:
33 | raise ValueError("wrong length of s")
34 | # train_number += 1
35 | # continue
36 | s_length_t1 = state_trace_length[train_number]
37 | s_length_t0 = state_trace_length[train_number - 1]
38 | if s_length_t1 > 10: # if trace length is too long
39 | s_length_t1 = 10
40 | if s_length_t0 > 10: # if trace length is too long
41 | s_length_t0 = 10
42 | try:
43 | s_reward_t1 = reward[train_number]
44 | s_reward_t0 = reward[train_number - 1]
45 | except IndexError:
46 | raise IndexError("s_reward wrong with index")
47 | train_number += 1
48 | if train_number + 1 == train_len:
49 | trace_length_index_t1 = s_length_t1 - 1
50 | trace_length_index_t0 = s_length_t0 - 1
51 | r_t0 = np.asarray([s_reward_t0[trace_length_index_t0]])
52 | r_t1 = np.asarray([s_reward_t1[trace_length_index_t1]])
53 | if r_t0 == [float(0)]:
54 | r_t0_combine = [float(0), float(0), float(0)]
55 | batch_return.append((s_t0, s_t1, r_t0_combine, s_length_t0, s_length_t1, 0, 0))
56 |
57 | if r_t1 == float(0):
58 | r_t1_combine = [float(0), float(0), float(1)]
59 | elif r_t1 == float(-1):
60 | r_t1_combine = [float(0), float(1), float(1)]
61 | elif r_t1 == float(1):
62 | r_t1_combine = [float(1), float(0), float(1)]
63 | else:
64 | raise ValueError("incorrect r_t1")
65 | batch_return.append((s_t1, s_t1, r_t1_combine, s_length_t1, s_length_t1, 1, 0))
66 |
67 | elif r_t0 == [float(-1)]:
68 | r_t0_combine = [float(0), float(1), float(0)]
69 | batch_return.append((s_t0, s_t1, r_t0_combine, s_length_t0, s_length_t1, 0, 0))
70 |
71 | if r_t1 == float(0):
72 | r_t1_combine = [float(0), float(0), float(1)]
73 | elif r_t1 == float(-1):
74 | r_t1_combine = [float(0), float(1), float(1)]
75 | elif r_t1 == float(1):
76 | r_t1_combine = [float(1), float(0), float(1)]
77 | else:
78 | raise ValueError("incorrect r_t1")
79 | batch_return.append((s_t1, s_t1, r_t1_combine, s_length_t1, s_length_t1, 1, 0))
80 |
81 | elif r_t0 == [float(1)]:
82 | r_t0_combine = [float(1), float(0), float(0)]
83 | batch_return.append((s_t0, s_t1, r_t0_combine, s_length_t0, s_length_t1, 0, 0))
84 |
85 | if r_t1 == float(0):
86 | r_t1_combine = [float(0), float(0), float(1)]
87 | elif r_t1 == float(-1):
88 | r_t1_combine = [float(0), float(1), float(1)]
89 | elif r_t1 == float(1):
90 | r_t1_combine = [float(1), float(0), float(1)]
91 | else:
92 | raise ValueError("incorrect r_t1")
93 | batch_return.append((s_t1, s_t1, r_t1_combine, s_length_t1, s_length_t1, 1, 0))
94 | else:
95 | raise ValueError("r_t0 wrong value")
96 |
97 | s_t0 = s_t1
98 | break
99 |
100 | trace_length_index_t0 = s_length_t0 - 1
101 | r_t0 = np.asarray([s_reward_t0[trace_length_index_t0]])
102 | if r_t0 != [float(0)]:
103 | # print r_t0
104 | if r_t0 == [float(-1)]:
105 | r_t0_combine = [float(0), float(1), float(0)]
106 | batch_return.append((s_t0, s_t1, r_t0_combine, s_length_t0, s_length_t1, 0, 1))
107 | elif r_t0 == [float(1)]:
108 | r_t0_combine = [float(1), float(0), float(0)]
109 | batch_return.append((s_t0, s_t1, r_t0_combine, s_length_t0, s_length_t1, 0, 1))
110 | else:
111 | raise ValueError("r_t0 wrong value")
112 | s_t0 = s_t1
113 | break
114 | r_t0_combine = [float(0), float(0), float(0)]
115 | batch_return.append((s_t0, s_t1, r_t0_combine, s_length_t0, s_length_t1, 0, 0))
116 | current_batch_length += 1
117 | s_t0 = s_t1
118 |
119 | return batch_return, train_number, s_t0
120 |
121 |
122 | def padding_hybrid_feature_input(hybrid_feature_input):
123 | """
124 | padding the empty state features with 0 (states won't be traced by Dynamic LSTM)
125 | :param hybrid_feature_input: the lists of features state to be padding
126 | :return:
127 | """
128 | current_list_length = len(hybrid_feature_input)
129 | padding_list_length = 10 - current_list_length
130 | for i in range(0, padding_list_length):
131 | hybrid_feature_input.append(np.asarray([float(0)] * FEATURE_NUMBER))
132 | return np.asarray(hybrid_feature_input)
133 |
134 |
135 | def padding_hybrid_reward(hybrid_reward):
136 | """
137 | padding the empty state rewards with 0 (rewards won't be traced by Dynamic LSTM)
138 | :param hybrid_reward: the lists of rewards to be padding
139 | :return:
140 | """
141 | current_list_length = len(hybrid_reward)
142 | padding_list_length = 10 - current_list_length
143 | for i in range(0, padding_list_length):
144 | hybrid_reward.append(0)
145 | return np.asarray(hybrid_reward)
146 |
147 |
148 | def compromise_state_trace_length(state_trace_length, state_input, reward, MAX_TRACE_LENGTH):
149 | """
150 | padding the features and rewards with 0, in order to get a proper format for LSTM
151 | :param state_trace_length: list of trace length
152 | :param state_input: list of state
153 | :param reward: list of rewards
154 | """
155 | state_trace_length_output = []
156 | for index in range(0, len(state_trace_length)):
157 | tl = state_trace_length[index]
158 | if tl >= 10:
159 | tl = 10
160 | if tl > MAX_TRACE_LENGTH:
161 | state_input_change_list = []
162 | state_input_org = state_input[index]
163 | reward_change_list = []
164 | reward_org = reward[index]
165 | for i in range(0, MAX_TRACE_LENGTH):
166 | state_input_change_list.append(state_input_org[tl - MAX_TRACE_LENGTH + i])
167 | # temp = reward_org[tl - MAX_TRACE_LENGTH + i]
168 | # if temp != 0:
169 | # print 'find miss reward'
170 | reward_change_list.append(reward_org[tl - MAX_TRACE_LENGTH + i])
171 |
172 | state_input_update = padding_hybrid_feature_input(state_input_change_list)
173 | state_input[index] = state_input_update
174 | reward_update = padding_hybrid_reward(reward_change_list)
175 | reward[index] = reward_update
176 |
177 | tl = MAX_TRACE_LENGTH
178 | state_trace_length_output.append(tl)
179 | return state_trace_length_output, state_input, reward
180 |
--------------------------------------------------------------------------------
/nn/td_two_tower_lstm.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 |
4 | class td_prediction_tt_embed:
5 | def __init__(self, feature_number, h_size, max_trace_length, learning_rate,
6 | output_layer_size=3,
7 | lstm_layer_num=2,
8 | dense_layer_num=2,
9 | model_name="tt_lstm",
10 | rnn_type="bp_last_step"):
11 | """
12 | init the model
13 | """
14 | self.feature_number = feature_number
15 | self.h_size = h_size
16 | self.max_trace_length = max_trace_length
17 | self.learning_rate = learning_rate
18 | self.rnn_type = rnn_type
19 | self.model_name = model_name
20 | self.lstm_layer_num = lstm_layer_num
21 | self.dense_layer_num = dense_layer_num
22 | self.output_layer_size = output_layer_size
23 |
24 | self.rnn_input_ph = None
25 | self.trace_lengths_ph = None
26 | self.home_away_indicator_ph = None
27 | self.y_ph = None
28 |
29 | self.lstm_cell_home_all = []
30 | self.lstm_cell_away_all = []
31 | self.dense_layer_weights = []
32 | self.dense_layer_bias = []
33 | self.embed_away_b = None
34 | self.embed_away_w = None
35 | self.embed_home_w = None
36 | self.embed_home_b = None
37 | self.readout = None
38 |
39 | def build(self):
40 | """
41 | define a shallow dynamic LSTM
42 | """
43 | with tf.name_scope(self.model_name):
44 | with tf.name_scope("tower-for-home"):
45 | with tf.name_scope("Home-LSTM-layer"):
46 | for i in range(self.lstm_layer_num):
47 | self.lstm_cell_home_all.append(
48 | tf.nn.rnn_cell.LSTMCell(num_units=self.h_size, state_is_tuple=True,
49 | initializer=tf.random_normal_initializer()))
50 | with tf.name_scope("Home_embed_layer"):
51 | self.embed_home_w = tf.get_variable('w_embed_home', [self.h_size, self.h_size],
52 | initializer=tf.contrib.layers.xavier_initializer())
53 | self.embed_home_b = tf.Variable(tf.zeros([self.h_size]), name="b_embed_home")
54 |
55 | with tf.name_scope("tower-for-away"):
56 | with tf.name_scope("Away-LSTM-layer"):
57 | for i in range(self.lstm_layer_num):
58 | self.lstm_cell_away_all.append(
59 | tf.nn.rnn_cell.LSTMCell(num_units=self.h_size, state_is_tuple=True,
60 | initializer=tf.random_normal_initializer()))
61 | with tf.name_scope("Away-embed-layer"):
62 | self.embed_away_w = tf.get_variable('w_embed_away', [self.h_size, self.h_size],
63 | initializer=tf.contrib.layers.xavier_initializer())
64 | self.embed_away_b = tf.Variable(tf.zeros([self.h_size]), name="b_embed_away")
65 |
66 | with tf.name_scope("Dense_Layer"):
67 | for i in range(self.dense_layer_num):
68 | w_input_size = self.h_size
69 | w_output_size = self.h_size if i < self.dense_layer_num - 1 else self.output_layer_size
70 | self.dense_layer_weights.append(tf.get_variable('w{0}_xaiver'.format(str(i)),
71 | [w_input_size, w_output_size],
72 | initializer=tf.contrib.layers.xavier_initializer()))
73 | self.dense_layer_bias.append(tf.Variable(tf.zeros([w_output_size]), name="b_{0}".format(str(i))))
74 |
75 | def call(self):
76 | """
77 | build the network
78 | :return:
79 | """
80 | with tf.name_scope(self.model_name):
81 | with tf.name_scope("tower-for-home"):
82 | with tf.name_scope("Home_LSTM_layer"):
83 | rnn_output = None
84 | for i in range(self.lstm_layer_num):
85 | rnn_input = self.rnn_input_ph if i == 0 else rnn_output
86 | rnn_output, rnn_state = tf.nn.dynamic_rnn( # while loop dynamic learning rnn
87 | inputs=rnn_input, cell=self.lstm_cell_home_all[i],
88 | sequence_length=self.trace_lengths_ph, dtype=tf.float32,
89 | scope=self.rnn_type + '_home_rnn_{0}'.format(str(i)))
90 | outputs = tf.stack(rnn_output)
91 | # Hack to build the indexing and retrieve the right output.
92 | self.batch_size = tf.shape(outputs)[0]
93 | # Start indices for each sample
94 | self.index = tf.range(0, self.batch_size) * self.max_trace_length + (self.trace_lengths_ph - 1)
95 | # Indexing
96 | rnn_last = tf.gather(tf.reshape(outputs, [-1, self.h_size]), self.index)
97 |
98 | with tf.name_scope("Home_embed_layer"):
99 | self.home_embed_layer = tf.matmul(rnn_last, self.embed_home_w) + self.embed_home_b
100 |
101 | with tf.name_scope("tower-for-away"):
102 | with tf.name_scope("Away_LSTM_layer"):
103 | rnn_output = None
104 | for i in range(self.lstm_layer_num):
105 | rnn_input = self.rnn_input_ph if i == 0 else rnn_output
106 | rnn_output, rnn_state = tf.nn.dynamic_rnn( # while loop dynamic learning rnn
107 | inputs=rnn_input, cell=self.lstm_cell_away_all[i],
108 | sequence_length=self.trace_lengths_ph, dtype=tf.float32,
109 | scope=self.rnn_type + '_away_rnn_{0}'.format(str(i)))
110 | outputs = tf.stack(rnn_output)
111 | # Hack to build the indexing and retrieve the right output.
112 | self.batch_size = tf.shape(outputs)[0]
113 | # Start indices for each sample
114 | self.index = tf.range(0, self.batch_size) * self.max_trace_length + (self.trace_lengths_ph - 1)
115 | # Indexing
116 | rnn_last = tf.gather(tf.reshape(outputs, [-1, self.h_size]), self.index)
117 |
118 | with tf.name_scope("Away_embed_layer"):
119 | self.away_embed_layer = tf.matmul(rnn_last, self.embed_away_w) + self.embed_away_b
120 |
121 | embed_layer = tf.where(condition=self.home_away_indicator_ph,
122 | x=self.home_embed_layer,
123 | y=self.away_embed_layer)
124 |
125 | with tf.name_scope('dense-layer'):
126 | dense_output = None
127 | for i in range(self.dense_layer_num):
128 | dense_input = embed_layer if i == 0 else dense_output
129 | dense_output = tf.matmul(dense_input, self.dense_layer_weights[i]) + self.dense_layer_bias[i]
130 | dense_output = tf.nn.relu(dense_output, name='activation_{0}'.format(str(i)))
131 |
132 | self.readout = dense_output
133 | with tf.name_scope("cost"):
134 | self.cost = tf.reduce_mean(tf.square(self.y_ph - self.readout))
135 | self.diff = tf.reduce_mean(tf.abs(self.y_ph - self.readout))
136 | tf.summary.histogram('cost', self.cost)
137 |
138 | with tf.name_scope("train"):
139 | self.train_step = tf.train.AdamOptimizer(learning_rate=self.learning_rate).minimize(self.cost)
140 |
141 | def initialize_ph(self):
142 | """
143 | initialize the place holder
144 | :return:
145 | """
146 | rnn_input_ph = tf.placeholder(dtype=tf.float32, shape=[None, self.max_trace_length,
147 | self.feature_number], name="rnn-input-ph")
148 | trace_lengths_ph = tf.placeholder(dtype=tf.int32, shape=[None], name="trace-length")
149 | home_away_indicator_ph = tf.cast(tf.placeholder(dtype=tf.int32, shape=[None], name="indicator-ph"), tf.bool)
150 | y_ph = tf.placeholder(dtype=tf.float32, shape=[None, self.output_layer_size])
151 |
152 | self.rnn_input_ph = rnn_input_ph
153 | self.trace_lengths_ph = trace_lengths_ph
154 | self.home_away_indicator_ph = home_away_indicator_ph
155 | self.y_ph = y_ph
156 |
157 |
158 | if __name__ == '__main__':
159 | """testing the model locally"""
160 | test_model = td_prediction_tt_embed(feature_number=25, h_size=32, max_trace_length=10, learning_rate=0.0001)
161 | test_model.initialize_ph()
162 | test_model.build()
163 | test_model.call()
164 | print "testing model"
165 |
--------------------------------------------------------------------------------
/td_three_prediction_lstm.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import tensorflow as tf
3 | import os
4 | import scipy.io as sio
5 | import numpy as np
6 | from nn.td_prediction_lstm_V3 import td_prediction_lstm_V3
7 | from nn.td_prediction_lstm_V4 import td_prediction_lstm_V4
8 | from utils import handle_trace_length, get_together_training_batch, compromise_state_trace_length
9 | from configuration import MODEL_TYPE, MAX_TRACE_LENGTH, FEATURE_NUMBER, BATCH_SIZE, GAMMA, H_SIZE, \
10 | model_train_continue, FEATURE_TYPE, ITERATE_NUM, learning_rate, SPORT, save_mother_dir
11 |
12 | LOG_DIR = save_mother_dir + "/models/hybrid_sl_log_NN/Scale-three-cut_together_log_train_feature" + str(
13 | FEATURE_TYPE) + "_batch" + str(
14 | BATCH_SIZE) + "_iterate" + str(
15 | ITERATE_NUM) + "_lr" + str(
16 | learning_rate) + "_" + str(MODEL_TYPE) + "_MaxTL" + str(MAX_TRACE_LENGTH)
17 | SAVED_NETWORK = save_mother_dir + "/models/hybrid_sl_saved_NN/Scale-three-cut_together_saved_networks_feature" + str(
18 | FEATURE_TYPE) + "_batch" + str(
19 | BATCH_SIZE) + "_iterate" + str(
20 | ITERATE_NUM) + "_lr" + str(
21 | learning_rate) + "_" + str(MODEL_TYPE) + "_MaxTL" + str(MAX_TRACE_LENGTH)
22 | DATA_STORE = "your-data-dir"
23 |
24 | DIR_GAMES_ALL = os.listdir(DATA_STORE)
25 | number_of_total_game = len(DIR_GAMES_ALL)
26 |
27 |
28 | def write_game_average_csv(data_record):
29 | """
30 | write the cost of training
31 | :param data_record: the recorded cost dict
32 | """
33 | try:
34 | if os.path.exists(LOG_DIR + '/avg_cost_record.csv'):
35 | with open(LOG_DIR + '/avg_cost_record.csv', 'a') as csvfile:
36 | fieldnames = (data_record[0]).keys()
37 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
38 | for record in data_record:
39 | writer.writerow(record)
40 | else:
41 | with open(LOG_DIR + '/avg_cost_record.csv', 'w') as csvfile:
42 | fieldnames = (data_record[0]).keys()
43 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
44 | writer.writeheader()
45 | for record in data_record:
46 | writer.writerow(record)
47 | except:
48 | if os.path.exists(LOG_DIR + '/avg_cost_record2.csv'):
49 | with open(LOG_DIR + '/avg_cost_record.csv', 'a') as csvfile:
50 | fieldnames = (data_record[0]).keys()
51 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
52 | for record in data_record:
53 | writer.writerow(record)
54 | else:
55 | with open(LOG_DIR + '/avg_cost_record2.csv', 'w') as csvfile:
56 | fieldnames = (data_record[0]).keys()
57 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
58 | writer.writeheader()
59 | for record in data_record:
60 | writer.writerow(record)
61 |
62 |
63 | def train_network(sess, model):
64 | """
65 | training thr neural network game by game
66 | :param sess: session of tf
67 | :param model: nn model
68 | :return:
69 | """
70 | game_number = 0
71 | global_counter = 0
72 | converge_flag = False
73 |
74 | # loading network
75 | saver = tf.train.Saver()
76 | merge = tf.summary.merge_all()
77 | train_writer = tf.summary.FileWriter(LOG_DIR, sess.graph)
78 | sess.run(tf.global_variables_initializer())
79 | if model_train_continue:
80 | checkpoint = tf.train.get_checkpoint_state(SAVED_NETWORK)
81 | if checkpoint and checkpoint.model_checkpoint_path:
82 | check_point_game_number = int((checkpoint.model_checkpoint_path.split("-"))[-1])
83 | game_number_checkpoint = check_point_game_number % number_of_total_game
84 | game_number = check_point_game_number
85 | game_starting_point = 0
86 | saver.restore(sess, checkpoint.model_checkpoint_path)
87 | print("Successfully loaded:", checkpoint.model_checkpoint_path)
88 | else:
89 | print("Could not find old network weights")
90 |
91 | game_diff_record_all = []
92 |
93 | while True:
94 | game_diff_record_dict = {}
95 | iteration_now = game_number / number_of_total_game + 1
96 | game_diff_record_dict.update({"Iteration": iteration_now})
97 | if converge_flag:
98 | break
99 | elif game_number >= number_of_total_game * ITERATE_NUM:
100 | break
101 | else:
102 | converge_flag = True
103 | for dir_game in DIR_GAMES_ALL:
104 |
105 | if checkpoint and checkpoint.model_checkpoint_path:
106 | if model_train_continue: # go the check point data
107 | game_starting_point += 1
108 | if game_number_checkpoint + 1 > game_starting_point:
109 | continue
110 |
111 | v_diff_record = []
112 | game_number += 1
113 | game_cost_record = []
114 | game_files = os.listdir(DATA_STORE + "/" + dir_game)
115 | for filename in game_files:
116 | if "dynamic_rnn_reward" in filename:
117 | reward_name = filename
118 | elif "dynamic_rnn_input" in filename:
119 | state_input_name = filename
120 | elif "trace" in filename:
121 | state_trace_length_name = filename
122 |
123 | reward = sio.loadmat(DATA_STORE + "/" + dir_game + "/" + reward_name)
124 | try:
125 | reward = reward['dynamic_rnn_reward']
126 | except:
127 | print("\n" + dir_game)
128 | raise ValueError("reward wrong")
129 | state_input = sio.loadmat(DATA_STORE + "/" + dir_game + "/" + state_input_name)
130 | state_input = (state_input['dynamic_feature_input'])
131 | state_trace_length = sio.loadmat(DATA_STORE + "/" + dir_game + "/" + state_trace_length_name)
132 | state_trace_length = (state_trace_length['hybrid_trace_length'])[0]
133 | state_trace_length = handle_trace_length(state_trace_length)
134 | state_trace_length, state_input, reward = compromise_state_trace_length(state_trace_length, state_input,
135 | reward, MAX_TRACE_LENGTH)
136 |
137 | print("\n load file" + str(dir_game) + " success")
138 | reward_count = sum(reward)
139 | print("reward number" + str(reward_count))
140 | if len(state_input) != len(reward) or len(state_trace_length) != len(reward):
141 | raise Exception('state length does not equal to reward length')
142 |
143 | train_len = len(state_input)
144 | train_number = 0
145 | s_t0 = state_input[train_number]
146 | train_number += 1
147 |
148 | while True:
149 | # try:
150 | batch_return, train_number, s_tl = get_together_training_batch(s_t0,
151 | state_input,
152 | reward,
153 | train_number,
154 | train_len,
155 | state_trace_length,
156 | BATCH_SIZE)
157 |
158 | # get the batch variables
159 | s_t0_batch = [d[0] for d in batch_return]
160 | s_t1_batch = [d[1] for d in batch_return]
161 | r_t_batch = [d[2] for d in batch_return]
162 | trace_t0_batch = [d[3] for d in batch_return]
163 | trace_t1_batch = [d[4] for d in batch_return]
164 | y_batch = []
165 |
166 | [outputs_t1, readout_t1_batch] = sess.run([model.outputs, model.read_out],
167 | feed_dict={model.trace_lengths: trace_t1_batch,
168 | model.rnn_input: s_t1_batch})
169 |
170 | for i in range(0, len(batch_return)):
171 | terminal = batch_return[i][5]
172 | cut = batch_return[i][6]
173 | # if terminal, only equals reward
174 | if terminal or cut:
175 | y_home = float((r_t_batch[i])[0])
176 | y_away = float((r_t_batch[i])[1])
177 | y_end = float((r_t_batch[i])[2])
178 | y_batch.append([y_home, y_away, y_end])
179 | break
180 | else:
181 | y_home = float((r_t_batch[i])[0]) + GAMMA * ((readout_t1_batch[i]).tolist())[0]
182 | y_away = float((r_t_batch[i])[1]) + GAMMA * ((readout_t1_batch[i]).tolist())[1]
183 | y_end = float((r_t_batch[i])[2]) + GAMMA * ((readout_t1_batch[i]).tolist())[2]
184 | y_batch.append([y_home, y_away, y_end])
185 |
186 | # perform gradient step
187 | y_batch = np.asarray(y_batch)
188 | [diff, read_out, cost_out, summary_train, _] = sess.run(
189 | [model.diff, model.read_out, model.cost, merge, model.train_step],
190 | feed_dict={model.y: y_batch,
191 | model.trace_lengths: trace_t0_batch,
192 | model.rnn_input: s_t0_batch})
193 |
194 | v_diff_record.append(diff)
195 |
196 | if cost_out > 0.0001:
197 | converge_flag = False
198 | global_counter += 1
199 | game_cost_record.append(cost_out)
200 | train_writer.add_summary(summary_train, global_step=global_counter)
201 | s_t0 = s_tl
202 |
203 | # print info
204 | if terminal or ((train_number - 1) / BATCH_SIZE) % 5 == 1:
205 | print("TIMESTEP:", train_number, "Game:", game_number)
206 | home_avg = sum(read_out[:, 0]) / len(read_out[:, 0])
207 | away_avg = sum(read_out[:, 1]) / len(read_out[:, 1])
208 | end_avg = sum(read_out[:, 2]) / len(read_out[:, 2])
209 | print("home average:{0}, away average:{1}, end average:{2}".format(str(home_avg), str(away_avg),
210 | str(end_avg)))
211 | print("cost of the network is" + str(cost_out))
212 |
213 | if terminal:
214 | # save progress after a game
215 | saver.save(sess, SAVED_NETWORK + '/' + SPORT + '-game-', global_step=game_number)
216 | v_diff_record_average = sum(v_diff_record) / len(v_diff_record)
217 | game_diff_record_dict.update({dir_game: v_diff_record_average})
218 | break
219 |
220 | # break
221 | cost_per_game_average = sum(game_cost_record) / len(game_cost_record)
222 | write_game_average_csv([{"iteration": str(game_number / number_of_total_game + 1), "game": game_number,
223 | "cost_per_game_average": cost_per_game_average}])
224 |
225 | game_diff_record_all.append(game_diff_record_dict)
226 |
227 |
228 | def train_start():
229 | if not os.path.isdir(LOG_DIR):
230 | os.mkdir(LOG_DIR)
231 | if not os.path.isdir(SAVED_NETWORK):
232 | os.mkdir(SAVED_NETWORK)
233 |
234 | sess = tf.InteractiveSession()
235 | if MODEL_TYPE == "v3":
236 | nn = td_prediction_lstm_V3(FEATURE_NUMBER, H_SIZE, MAX_TRACE_LENGTH, learning_rate)
237 | elif MODEL_TYPE == "v4":
238 | nn = td_prediction_lstm_V4(FEATURE_NUMBER, H_SIZE, MAX_TRACE_LENGTH, learning_rate)
239 | else:
240 | raise ValueError("MODEL_TYPE error")
241 | train_network(sess, nn)
242 |
243 |
244 | if __name__ == '__main__':
245 | train_start()
246 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 | 1524683863507
216 |
217 |
218 | 1524683863507
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 | file://$PROJECT_DIR$/td_three_prediction_lstm.py
254 | 235
255 |
256 |
257 | file://$PROJECT_DIR$/td_three_prediction_lstm.py
258 | 237
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
--------------------------------------------------------------------------------
/bak/player_ranking_match_by_match_td_lstm.py:
--------------------------------------------------------------------------------
1 | import ast
2 | import unicodedata
3 | import csv
4 | import os
5 | import scipy.io as sio
6 | from scipy.stats.stats import pearsonr
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 |
10 |
11 | class GoalImpactMetric:
12 |
13 | def __init__(self):
14 | self.FEATURE_TYPE = 5
15 | self.calibration = True
16 | self.ITERATE_NUM = 30
17 | self.MODEL_TYPE = "v4"
18 | self.BATCH_SIZE = 32
19 | self.learning_rate = 1e-4
20 | self.pre_initialize = False
21 | self.MAX_TRACE_LENGTH = 2
22 | self.if_correct_velocity = "_v_correct_"
23 | self.ROUND_NUMBER = 60
24 |
25 | self.IS_POSSIBILITY = True
26 | self.IS_DIFFERENCE = True
27 | if self.IS_DIFFERENCE:
28 | self.DIFFERENCE_TYPE = "back_difference_"
29 |
30 | self.PLAYER_ID_DICT_ALL_BY_MATCH = {}
31 | self.PLAYER_ID_DICT_ALL = {}
32 | self.PLAYER_INTEREST = ['G', 'A', 'P', 'PlayerName', 'GP', 'PlusMinus', 'PIM', 'PointPerGame', 'PPG', 'PPP',
33 | 'SHG', 'SHP',
34 | 'GWG', 'OTG', 'S', 'ShootingPercentage', 'TOIPerGame', 'ShiftsPerGame',
35 | 'FaceoffWinPercentage']
36 |
37 | if self.learning_rate == 1e-6:
38 | self.learning_rate_write = 6
39 | elif self.learning_rate == 1e-5:
40 | self.learning_rate_write = 5
41 | elif self.learning_rate == 1e-4:
42 | self.learning_rate_write = 4
43 | else:
44 | raise ValueError("undefined learning_rate")
45 |
46 | if self.pre_initialize:
47 | self.pre_initialize_save = "_pre_initialize"
48 | else:
49 | self.pre_initialize_save = ""
50 |
51 | self.model_data_store_dir = "/cs/oschulte/Galen/Hockey-data-entire/Hybrid-RNN-Hockey-Training-All-feature{0}-scale" \
52 | "-neg_reward{1}_length-dynamic".format(str(self.FEATURE_TYPE),
53 | self.if_correct_velocity)
54 |
55 | # self.model_data_store_dir = "/cs/oschulte/Galen/Hockey-data-entire/Hockey-Training-All-feature{0}-scale-neg_reward{1}".format(str(self.FEATURE_TYPE), self.if_correct_velocity)
56 |
57 | self.data_path = "/cs/oschulte/Galen/Hockey-data-entire/Hockey-Match-All-data"
58 | self.dir_all = os.listdir(self.data_path)
59 |
60 | self.player_info_dir = "../player_statistic/players_2015_2016.csv"
61 |
62 | self.skater_info_dir = "../player_statistic/skater_stats_2015_2016_original.csv"
63 |
64 | self.data_name = "model_three_cut_together_predict_Feature{0}_Iter{1}_lr{2}_Batch{3}_MaxLength{4}_Type{5}{6}".format(
65 | str(self.FEATURE_TYPE),
66 | str(self.ITERATE_NUM),
67 | str(self.learning_rate_write),
68 | str(self.BATCH_SIZE),
69 | str(self.MAX_TRACE_LENGTH),
70 | str(self.MODEL_TYPE),
71 | self.if_correct_velocity)
72 |
73 | # state_data_name = "model_state_cut_together_predict_Fea{0}_Iter{1}_lr{2}_Batch{3}_MaxLength{4}_Type{5}".format(
74 | # str(FEATURE_TYPE), str(ITERATE_NUM), str(6), str(8), str(MAX_TRACE_LENGTH), MODEL_TYPE)
75 |
76 | def aggregate_values(self):
77 | """
78 | aggregate value for each player
79 | """
80 | for calibration_dir_game in os.listdir(self.model_data_store_dir):
81 | # model_state_data_name = state_model_data_store_dir + "/" + calibration_dir_game + "/" + state_data_name + ".mat"
82 | # model_state_data = (sio.loadmat(model_state_data_name))[state_data_name]
83 | for file_name in os.listdir(self.model_data_store_dir + "/" + calibration_dir_game):
84 | if file_name == self.data_name + ".mat":
85 | model_data_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
86 | model_data = (sio.loadmat(model_data_name))[self.data_name]
87 | elif file_name.startswith("playerId"):
88 | playerIds_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
89 | playerIds = (sio.loadmat(playerIds_name))["playerId"][0]
90 | elif file_name.startswith("home_identifier"):
91 | home_identifier_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
92 | home_identifier = (sio.loadmat(home_identifier_name))["home_identifier"][0]
93 | else:
94 | continue
95 |
96 | for player_Index in range(0, len(playerIds)):
97 | playerId = playerIds[player_Index]
98 | model_value = model_data[player_Index]
99 | # model_state_value = model_state_data[player_Index]
100 | ishome = home_identifier[player_Index]
101 | player_value = self.PLAYER_ID_DICT_ALL.get(playerId)
102 | if player_value is None:
103 | if ishome:
104 | if self.IS_POSSIBILITY:
105 | self.PLAYER_ID_DICT_ALL.update(
106 | {playerId: {
107 | "value all": (model_value[0] - model_value[1]) / (
108 | model_value[0] + model_value[1] + abs(model_value[2]))}})
109 | # "state value": (model_state_value[0] - model_state_value[1]) / (
110 | # model_state_value[0] + model_state_value[1])}})
111 | else:
112 | self.PLAYER_ID_DICT_ALL.update({playerId: {"value all": model_value[0] - model_value[1]}})
113 | # "state value": model_state_value[0] - model_state_value[1]}})
114 | else:
115 | if self.IS_POSSIBILITY:
116 | self.PLAYER_ID_DICT_ALL.update(
117 | {playerId: {
118 | "value all": (model_value[1] - model_value[0]) / (
119 | model_value[0] + model_value[1] + abs(model_value[2]))}})
120 | # "state value": (model_state_value[1] - model_state_value[0]) / (
121 | # model_state_value[0] + model_state_value[1])}})
122 | else:
123 | self.PLAYER_ID_DICT_ALL.update({playerId: {"value all": model_value[1] - model_value[0]}})
124 | # "state value": model_state_value[1] - model_state_value[0]}})
125 | else:
126 | if ishome:
127 | if self.IS_POSSIBILITY:
128 | player_value_number = player_value.get("value all") + (model_value[0] - model_value[1]) / (
129 | model_value[0] + model_value[1] + abs(model_value[2]))
130 | # player_state_value_number = player_value.get("state value") + (model_state_value[0] - model_state_value[1])/(model_state_value[0] + model_state_value[1])
131 | else:
132 | player_value_number = player_value.get("value all") + model_value[0] - model_value[1]
133 | # player_state_value_number = player_value.get("state value") + model_state_value[0] - \
134 | # model_state_value[1]
135 | else:
136 | if self.IS_POSSIBILITY:
137 | player_value_number = player_value.get("value all") + (model_value[1] - model_value[0]) / (
138 | model_value[0] + model_value[1] + abs(model_value[2]))
139 | # player_state_value_number = player_value.get("state value") + (model_state_value[1] - model_state_value[0])/(model_state_value[0] + model_state_value[1])
140 | else:
141 | player_value_number = player_value.get("value all") + model_value[1] - model_value[0]
142 | # player_state_value_number = player_value.get("state value") + model_state_value[1] - \
143 | # model_state_value[0]
144 | self.PLAYER_ID_DICT_ALL.update(
145 | {playerId: {"value all": player_value_number}})
146 | # {playerId: {"value": player_value_number, "state value": player_state_value_number}}), "state value": player_state_value_number}})
147 | # break
148 |
149 | def aggregate_diff_values(self):
150 | """
151 | aggregate value for each player
152 | """
153 | for calibration_dir_game in os.listdir(self.model_data_store_dir):
154 | # model_state_data_name = state_model_data_store_dir + "/" + calibration_dir_game + "/" + state_data_name + ".mat"
155 | # model_state_data = (sio.loadmat(model_state_data_name))[state_data_name]
156 | for file_name in os.listdir(self.model_data_store_dir + "/" + calibration_dir_game):
157 | if file_name == self.data_name + ".mat":
158 | model_data_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
159 | model_data = (sio.loadmat(model_data_name))[self.data_name]
160 | elif file_name.startswith("playerId"):
161 | playerIds_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
162 | playerIds = (sio.loadmat(playerIds_name))["playerId"][0]
163 | elif file_name.startswith("home_identifier"):
164 | home_identifier_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
165 | home_identifier = (sio.loadmat(home_identifier_name))["home_identifier"][0]
166 | elif "training_data_dict_all_name" in file_name:
167 | training_data_dict_all_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
168 | training_data_dict_all = ((sio.loadmat(training_data_dict_all_name))["training_data_dict_all_name"])
169 | else:
170 | continue
171 |
172 | for player_Index in range(0, len(playerIds)):
173 | playerId = playerIds[player_Index]
174 | model_value = model_data[player_Index]
175 |
176 | if player_Index - 1 >= 0:
177 | training_data_dict_all_pre = training_data_dict_all[player_Index - 1]
178 | training_data_dict_all_pre_str = unicodedata.normalize('NFKD', training_data_dict_all_pre).encode(
179 | 'ascii', 'ignore')
180 | training_data_dict_all_pre_dict = ast.literal_eval(training_data_dict_all_pre_str)
181 |
182 | if training_data_dict_all_pre_dict.get('action') == "goal":
183 | model_value_pre = model_data[player_Index]
184 | else:
185 | model_value_pre = model_data[player_Index - 1]
186 | else:
187 | model_value_pre = model_data[player_Index]
188 |
189 | if player_Index + 1 < len(playerIds):
190 | training_data_dict_all_nex = training_data_dict_all[player_Index]
191 | training_data_dict_all_nex_str = unicodedata.normalize('NFKD', training_data_dict_all_nex).encode(
192 | 'ascii', 'ignore')
193 | training_data_dict_all_nex_dict = ast.literal_eval(training_data_dict_all_nex_str)
194 |
195 | if training_data_dict_all_nex_dict.get('action') == "goal":
196 | model_value_nex = model_data[player_Index]
197 | else:
198 | model_value_nex = model_data[player_Index + 1]
199 |
200 | else:
201 | model_value_nex = model_data[player_Index]
202 |
203 | if model_value[2] < 0:
204 | model_value[2] = 0
205 | if model_value_pre[2] < 0:
206 | model_value_pre[2] = 0
207 | if model_value_nex[2] < 0:
208 | model_value_nex[2] = 0
209 |
210 | ishome = home_identifier[player_Index]
211 | player_value = self.PLAYER_ID_DICT_ALL.get(playerId)
212 | if player_value is None:
213 | if ishome:
214 | if self.IS_POSSIBILITY:
215 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
216 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
217 | end_model_value = abs(model_value[2]) / (
218 | model_value[0] + model_value[1] + abs(model_value[2]))
219 |
220 | home_model_value_pre = model_value_pre[0] / (
221 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
222 | away_model_value_pre = model_value_pre[1] / (
223 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
224 | end_model_value_pre = abs(model_value_pre[2]) / (
225 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
226 |
227 | home_model_value_nex = model_value_nex[0] / (
228 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
229 | away_model_value_nex = model_value_nex[1] / (
230 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
231 | end_model_value_nex = abs(model_value_nex[2]) / (
232 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
233 |
234 | if self.DIFFERENCE_TYPE == "back_difference_":
235 | q_value = (home_model_value - home_model_value_pre) - (
236 | away_model_value - away_model_value_pre)
237 | elif self.DIFFERENCE_TYPE == "front_difference_":
238 | q_value = (home_model_value_nex - home_model_value) - (
239 | away_model_value_nex - away_model_value)
240 | elif self.DIFFERENCE_TYPE == "skip_difference_":
241 | q_value = (home_model_value_nex - home_model_value_pre) - (
242 | away_model_value_nex - away_model_value_pre)
243 |
244 | self.PLAYER_ID_DICT_ALL.update(
245 | {playerId: {
246 | "value all": q_value}})
247 | # "state value": (model_state_value[0] - model_state_value[1]) / (
248 | # model_state_value[0] + model_state_value[1])}})
249 | else:
250 | home_model_value = model_value[0]
251 | away_model_value = model_value[1]
252 | end_model_value = abs(model_value[2])
253 | home_model_value_pre = model_value_pre[0]
254 | away_model_value_pre = model_value_pre[1]
255 | end_model_value_pre = abs(model_value_pre[2])
256 | home_model_value_nex = model_value_nex[0]
257 | away_model_value_nex = model_value_nex[1]
258 | end_model_value_nex = abs(model_value_nex[2])
259 |
260 | if self.DIFFERENCE_TYPE == "back_difference_":
261 | q_value = (home_model_value - home_model_value_pre) - (
262 | away_model_value - away_model_value_pre)
263 | elif self.DIFFERENCE_TYPE == "front_difference_":
264 | q_value = (home_model_value_nex - home_model_value) - (
265 | away_model_value_nex - away_model_value)
266 | elif self.DIFFERENCE_TYPE == "skip_difference_":
267 | q_value = (home_model_value_nex - home_model_value_pre) - (
268 | away_model_value_nex - away_model_value_pre)
269 |
270 | self.PLAYER_ID_DICT_ALL.update({playerId: {"value all": q_value}})
271 | # "state value": model_state_value[0] - model_state_value[1]}})
272 | else:
273 | if self.IS_POSSIBILITY:
274 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
275 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
276 | end_model_value = abs(model_value[2]) / (
277 | model_value[0] + model_value[1] + abs(model_value[2]))
278 |
279 | home_model_value_pre = model_value_pre[0] / (
280 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
281 | away_model_value_pre = model_value_pre[1] / (
282 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
283 | end_model_value_pre = abs(model_value_pre[2]) / (
284 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
285 |
286 | home_model_value_nex = model_value_nex[0] / (
287 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
288 | away_model_value_nex = model_value_nex[1] / (
289 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
290 | end_model_value_nex = abs(model_value_nex[2]) / (
291 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
292 |
293 | if self.DIFFERENCE_TYPE == "back_difference_":
294 | q_value = (away_model_value - away_model_value_pre) - (
295 | home_model_value - home_model_value_pre)
296 | elif self.DIFFERENCE_TYPE == "front_difference_":
297 | q_value = (away_model_value_nex - away_model_value) - (
298 | home_model_value_nex - home_model_value)
299 | elif self.DIFFERENCE_TYPE == "skip_difference_":
300 | q_value = (away_model_value_nex - away_model_value_pre) - (
301 | home_model_value_nex - home_model_value_pre
302 | )
303 |
304 | self.PLAYER_ID_DICT_ALL.update(
305 | {playerId: {
306 | "value all": q_value}})
307 | else:
308 | home_model_value = model_value[0]
309 | away_model_value = model_value[1]
310 | end_model_value = abs(model_value[2])
311 | home_model_value_pre = model_value_pre[0]
312 | away_model_value_pre = model_value_pre[1]
313 | end_model_value_pre = abs(model_value_pre[2])
314 | home_model_value_nex = model_value_nex[0]
315 | away_model_value_nex = model_value_nex[1]
316 | end_model_value_nex = abs(model_value_nex[2])
317 |
318 | if self.DIFFERENCE_TYPE == "back_difference_":
319 | q_value = (away_model_value - away_model_value_pre) - (
320 | home_model_value - home_model_value_pre)
321 | elif self.DIFFERENCE_TYPE == "front_difference_":
322 | q_value = (away_model_value_nex - away_model_value) - (
323 | home_model_value_nex - home_model_value)
324 | elif self.DIFFERENCE_TYPE == "skip_difference_":
325 | q_value = (away_model_value_nex - away_model_value_pre) - (
326 | home_model_value_nex - home_model_value_pre
327 | )
328 |
329 | self.PLAYER_ID_DICT_ALL.update(
330 | {playerId: {
331 | "value all": q_value}})
332 | else:
333 | if ishome:
334 | if self.IS_POSSIBILITY:
335 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
336 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
337 | end_model_value = abs(model_value[2]) / (
338 | model_value[0] + model_value[1] + abs(model_value[2]))
339 |
340 | home_model_value_pre = model_value_pre[0] / (
341 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
342 | away_model_value_pre = model_value_pre[1] / (
343 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
344 | end_model_value_pre = abs(model_value_pre[2]) / (
345 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
346 |
347 | home_model_value_nex = model_value_nex[0] / (
348 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
349 | away_model_value_nex = model_value_nex[1] / (
350 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
351 | end_model_value_nex = abs(model_value_nex[2]) / (
352 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
353 |
354 | if self.DIFFERENCE_TYPE == "back_difference_":
355 | q_value = (home_model_value - home_model_value_pre) - (
356 | away_model_value - away_model_value_pre)
357 | elif self.DIFFERENCE_TYPE == "front_difference_":
358 | q_value = (home_model_value_nex - home_model_value) - (
359 | away_model_value_nex - away_model_value)
360 | elif self.DIFFERENCE_TYPE == "skip_difference_":
361 | q_value = (home_model_value_nex - home_model_value_pre) - (
362 | away_model_value_nex - away_model_value_pre)
363 |
364 | player_value_number = player_value.get("value all") + q_value
365 | else:
366 | home_model_value = model_value[0]
367 | away_model_value = model_value[1]
368 | end_model_value = abs(model_value[2])
369 | home_model_value_pre = model_value_pre[0]
370 | away_model_value_pre = model_value_pre[1]
371 | end_model_value_pre = abs(model_value_pre[2])
372 | home_model_value_nex = model_value_nex[0]
373 | away_model_value_nex = model_value_nex[1]
374 | end_model_value_nex = abs(model_value_nex[2])
375 |
376 | if self.DIFFERENCE_TYPE == "back_difference_":
377 | q_value = (home_model_value - home_model_value_pre) - (
378 | away_model_value - away_model_value_pre)
379 | elif self.DIFFERENCE_TYPE == "front_difference_":
380 | q_value = (home_model_value_nex - home_model_value) - (
381 | away_model_value_nex - away_model_value)
382 | elif self.DIFFERENCE_TYPE == "skip_difference_":
383 | q_value = (home_model_value_nex - home_model_value_pre) - (
384 | away_model_value_nex - away_model_value_pre)
385 |
386 | player_value_number = player_value.get("value all") + q_value
387 |
388 | else:
389 | if self.IS_POSSIBILITY:
390 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
391 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
392 | end_model_value = abs(model_value[2]) / (
393 | model_value[0] + model_value[1] + abs(model_value[2]))
394 |
395 | home_model_value_pre = model_value_pre[0] / (
396 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
397 | away_model_value_pre = model_value_pre[1] / (
398 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
399 | end_model_value_pre = abs(model_value_pre[2]) / (
400 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
401 |
402 | home_model_value_nex = model_value_nex[0] / (
403 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
404 | away_model_value_nex = model_value_nex[1] / (
405 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
406 | end_model_value_nex = abs(model_value_nex[2]) / (
407 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
408 |
409 | if self.DIFFERENCE_TYPE == "back_difference_":
410 | q_value = (away_model_value - away_model_value_pre) - (
411 | home_model_value - home_model_value_pre)
412 | elif self.DIFFERENCE_TYPE == "front_difference_":
413 | q_value = (away_model_value_nex - away_model_value) - (
414 | home_model_value_nex - home_model_value)
415 | elif self.DIFFERENCE_TYPE == "skip_difference_":
416 | q_value = (away_model_value_nex - away_model_value_pre) - (
417 | home_model_value_nex - home_model_value_pre
418 | )
419 | player_value_number = player_value.get("value all") + q_value
420 |
421 |
422 | else:
423 | home_model_value = model_value[0]
424 | away_model_value = model_value[1]
425 | end_model_value = abs(model_value[2])
426 | home_model_value_pre = model_value_pre[0]
427 | away_model_value_pre = model_value_pre[1]
428 | end_model_value_pre = abs(model_value_pre[2])
429 | home_model_value_nex = model_value_nex[0]
430 | away_model_value_nex = model_value_nex[1]
431 | end_model_value_nex = abs(model_value_nex[2])
432 |
433 | if self.DIFFERENCE_TYPE == "back_difference_":
434 | q_value = (away_model_value - away_model_value_pre) - (
435 | home_model_value - home_model_value_pre)
436 | elif self.DIFFERENCE_TYPE == "front_difference_":
437 | q_value = (away_model_value_nex - away_model_value) - (
438 | home_model_value_nex - home_model_value)
439 | elif self.DIFFERENCE_TYPE == "skip_difference_":
440 | q_value = (away_model_value_nex - away_model_value_pre) - (
441 | home_model_value_nex - home_model_value_pre
442 | )
443 | player_value_number = player_value.get("value all") + q_value
444 |
445 | self.PLAYER_ID_DICT_ALL.update(
446 | {playerId: {"value all": player_value_number}})
447 | # {playerId: {"value": player_value_number, "state value": player_state_value_number}}), "state value": player_state_value_number}})
448 | # break
449 |
450 | def aggregate_match_values(self, game_target_dir, teamId_target):
451 | """
452 |
453 | :param game_target_dir:
454 | :param teamId_target:
455 | :return:
456 | """
457 | for file_name in os.listdir(self.model_data_store_dir + "/" + game_target_dir):
458 | if file_name == self.data_name + ".mat":
459 | model_data_name = self.model_data_store_dir + "/" + game_target_dir + "/" + file_name
460 | model_data = (sio.loadmat(model_data_name))[self.data_name]
461 | elif file_name.startswith("playerId"):
462 | playerIds_name = self.model_data_store_dir + "/" + game_target_dir + "/" + file_name
463 | playerIds = (sio.loadmat(playerIds_name))["playerId"][0]
464 | elif file_name.startswith("teamId"):
465 | teamIds_name = self.model_data_store_dir + "/" + game_target_dir + "/" + file_name
466 | teamIds = (sio.loadmat(teamIds_name))["teamId"][0]
467 | elif file_name.startswith("home_identifier"):
468 | home_identifier_name = self.model_data_store_dir + "/" + game_target_dir + "/" + file_name
469 | home_identifier = (sio.loadmat(home_identifier_name))["home_identifier"][0]
470 | else:
471 | continue
472 |
473 | for player_Index in range(0, len(playerIds)):
474 | playerId = playerIds[player_Index]
475 | teamId = teamIds[player_Index]
476 | if int(teamId_target) == int(teamId):
477 | model_value = model_data[player_Index]
478 | # model_state_value = model_state_data[player_Index]
479 | ishome = home_identifier[player_Index]
480 | player_value = self.PLAYER_ID_DICT_ALL_BY_MATCH.get(playerId)
481 | if player_value is None:
482 | if ishome:
483 | if self.IS_POSSIBILITY:
484 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
485 | {playerId: {
486 | "value": (model_value[0] - model_value[1]) / (
487 | model_value[0] + model_value[1] + abs(model_value[2]))}})
488 | # "state value": (model_state_value[0] - model_state_value[1]) / (
489 | # model_state_value[0] + model_state_value[1])}})
490 | else:
491 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
492 | {playerId: {"value": model_value[0] - model_value[1]}})
493 | # "state value": model_state_value[0] - model_state_value[1]}})
494 | else:
495 | if self.IS_POSSIBILITY:
496 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
497 | {playerId: {
498 | "value": (model_value[1] - model_value[0]) / (
499 | model_value[0] + model_value[1] + abs(model_value[2]))}})
500 | # "state value": (model_state_value[1] - model_state_value[0]) / (
501 | # model_state_value[0] + model_state_value[1])}})
502 | else:
503 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
504 | {playerId: {"value": model_value[1] - model_value[0]}})
505 | # "state value": model_state_value[1] - model_state_value[0]}})
506 | else:
507 | if ishome:
508 | if self.IS_POSSIBILITY:
509 | player_value_number = player_value.get("value") + (model_value[0] - model_value[1]) / (
510 | model_value[0] + model_value[1] + abs(model_value[2]))
511 | # player_state_value_number = player_value.get("state value") + (model_state_value[0] - model_state_value[1])/(model_state_value[0] + model_state_value[1])
512 | else:
513 | player_value_number = player_value.get("value") + model_value[0] - model_value[1]
514 | # player_state_value_number = player_value.get("state value") + model_state_value[0] - \
515 | # model_state_value[1]
516 | else:
517 | if self.IS_POSSIBILITY:
518 | player_value_number = player_value.get("value") + (model_value[1] - model_value[0]) / (
519 | model_value[0] + model_value[1] + abs(model_value[2]))
520 | # player_state_value_number = player_value.get("state value") + (model_state_value[1] - model_state_value[0])/(model_state_value[0] + model_state_value[1])
521 | else:
522 | player_value_number = player_value.get("value") + model_value[1] - model_value[0]
523 | # player_state_value_number = player_value.get("state value") + model_state_value[1] - \
524 | # model_state_value[0]
525 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
526 | {playerId: {"value": player_value_number}})
527 | # {playerId: {"value": player_value_number, "state value": player_state_value_number}}), "state value": player_state_value_number}})
528 | # break
529 |
530 | def aggregate_match_diff_values(self, calibration_dir_game, teamId_target):
531 | for file_name in os.listdir(self.model_data_store_dir + "/" + calibration_dir_game):
532 | if file_name == self.data_name + ".mat":
533 | model_data_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
534 | model_data = (sio.loadmat(model_data_name))[self.data_name]
535 | elif file_name.startswith("playerId"):
536 | playerIds_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
537 | playerIds = (sio.loadmat(playerIds_name))["playerId"][0]
538 | elif file_name.startswith("teamId"):
539 | teamIds_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
540 | teamIds = (sio.loadmat(teamIds_name))["teamId"][0]
541 | elif file_name.startswith("home_identifier"):
542 | home_identifier_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
543 | home_identifier = (sio.loadmat(home_identifier_name))["home_identifier"][0]
544 | elif "training_data_dict_all_name" in file_name:
545 | training_data_dict_all_name = self.model_data_store_dir + "/" + calibration_dir_game + "/" + file_name
546 | training_data_dict_all = ((sio.loadmat(training_data_dict_all_name))["training_data_dict_all_name"])
547 | else:
548 | continue
549 |
550 | for player_Index in range(0, len(playerIds)):
551 | playerId = playerIds[player_Index]
552 | teamId = teamIds[player_Index]
553 | if int(teamId_target) == int(teamId):
554 | model_value = model_data[player_Index]
555 | if player_Index - 1 >= 0:
556 | training_data_dict_all_pre = training_data_dict_all[player_Index - 1]
557 | training_data_dict_all_pre_str = unicodedata.normalize('NFKD', training_data_dict_all_pre).encode(
558 | 'ascii', 'ignore')
559 | training_data_dict_all_pre_dict = ast.literal_eval(training_data_dict_all_pre_str)
560 |
561 | if training_data_dict_all_pre_dict.get('action') == "goal":
562 | model_value_pre = model_data[player_Index]
563 | else:
564 | model_value_pre = model_data[player_Index - 1]
565 | else:
566 | model_value_pre = model_data[player_Index]
567 |
568 | if player_Index + 1 <= len(playerIds):
569 | training_data_dict_all_nex = training_data_dict_all[player_Index]
570 | training_data_dict_all_nex_str = unicodedata.normalize('NFKD', training_data_dict_all_nex).encode(
571 | 'ascii', 'ignore')
572 | training_data_dict_all_nex_dict = ast.literal_eval(training_data_dict_all_nex_str)
573 |
574 | if training_data_dict_all_nex_dict.get('action') == "goal":
575 | model_value_nex = model_data[player_Index]
576 | else:
577 | model_value_nex = model_data[player_Index - 1]
578 |
579 | else:
580 | model_value_nex = model_data[player_Index]
581 |
582 | if model_value[2] < 0:
583 | model_value[2] = 0
584 | if model_value_pre[2] < 0:
585 | model_value_pre[2] = 0
586 | if model_value_nex[2] < 0:
587 | model_value_nex[2] = 0
588 |
589 | ishome = home_identifier[player_Index]
590 | player_value = self.PLAYER_ID_DICT_ALL_BY_MATCH.get(playerId)
591 | if player_value is None:
592 | if ishome:
593 | if self.IS_POSSIBILITY:
594 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
595 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
596 | end_model_value = abs(model_value[2]) / (
597 | model_value[0] + model_value[1] + abs(model_value[2]))
598 |
599 | home_model_value_pre = model_value_pre[0] / (
600 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
601 | away_model_value_pre = model_value_pre[1] / (
602 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
603 | end_model_value_pre = abs(model_value_pre[2]) / (
604 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
605 |
606 | home_model_value_nex = model_value_nex[0] / (
607 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
608 | away_model_value_nex = model_value_nex[1] / (
609 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
610 | end_model_value_nex = abs(model_value_nex[2]) / (
611 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
612 |
613 | if self.DIFFERENCE_TYPE == "back_difference_":
614 | q_value = (home_model_value - home_model_value_pre) - (
615 | away_model_value - away_model_value_pre)
616 | elif self.DIFFERENCE_TYPE == "front_difference_":
617 | q_value = (home_model_value_nex - home_model_value) - (
618 | away_model_value_nex - away_model_value)
619 | elif self.DIFFERENCE_TYPE == "skip_difference_":
620 | q_value = (home_model_value_nex - home_model_value_pre) - (
621 | away_model_value_nex - away_model_value_pre)
622 |
623 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
624 | {playerId: {
625 | "value": q_value}})
626 | # "state value": (model_state_value[0] - model_state_value[1]) / (
627 | # model_state_value[0] + model_state_value[1])}})
628 | else:
629 | home_model_value = model_value[0]
630 | away_model_value = model_value[1]
631 | end_model_value = abs(model_value[2])
632 | home_model_value_pre = model_value_pre[0]
633 | away_model_value_pre = model_value_pre[1]
634 | end_model_value_pre = abs(model_value_pre[2])
635 | home_model_value_nex = model_value_nex[0]
636 | away_model_value_nex = model_value_nex[1]
637 | end_model_value_nex = abs(model_value_nex[2])
638 |
639 | if self.DIFFERENCE_TYPE == "back_difference_":
640 | q_value = (home_model_value - home_model_value_pre) - (
641 | away_model_value - away_model_value_pre)
642 | elif self.DIFFERENCE_TYPE == "front_difference_":
643 | q_value = (home_model_value_nex - home_model_value) - (
644 | away_model_value_nex - away_model_value)
645 | elif self.DIFFERENCE_TYPE == "skip_difference_":
646 | q_value = (home_model_value_nex - home_model_value_pre) - (
647 | away_model_value_nex - away_model_value_pre)
648 |
649 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update({playerId: {"value": q_value}})
650 | # "state value": model_state_value[0] - model_state_value[1]}})
651 | else:
652 | if self.IS_POSSIBILITY:
653 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
654 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
655 | end_model_value = abs(model_value[2]) / (
656 | model_value[0] + model_value[1] + abs(model_value[2]))
657 |
658 | home_model_value_pre = model_value_pre[0] / (
659 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
660 | away_model_value_pre = model_value_pre[1] / (
661 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
662 | end_model_value_pre = abs(model_value_pre[2]) / (
663 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
664 |
665 | home_model_value_nex = model_value_nex[0] / (
666 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
667 | away_model_value_nex = model_value_nex[1] / (
668 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
669 | end_model_value_nex = abs(model_value_nex[2]) / (
670 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
671 |
672 | if self.DIFFERENCE_TYPE == "back_difference_":
673 | q_value = (away_model_value - away_model_value_pre) - (
674 | home_model_value - home_model_value_pre)
675 | elif self.DIFFERENCE_TYPE == "front_difference_":
676 | q_value = (away_model_value_nex - away_model_value) - (
677 | home_model_value_nex - home_model_value)
678 | elif self.DIFFERENCE_TYPE == "skip_difference_":
679 | q_value = (away_model_value_nex - away_model_value_pre) - (
680 | home_model_value_nex - home_model_value_pre
681 | )
682 |
683 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
684 | {playerId: {
685 | "value": q_value}})
686 | else:
687 | home_model_value = model_value[0]
688 | away_model_value = model_value[1]
689 | end_model_value = abs(model_value[2])
690 | home_model_value_pre = model_value_pre[0]
691 | away_model_value_pre = model_value_pre[1]
692 | end_model_value_pre = abs(model_value_pre[2])
693 | home_model_value_nex = model_value_nex[0]
694 | away_model_value_nex = model_value_nex[1]
695 | end_model_value_nex = abs(model_value_nex[2])
696 |
697 | if self.DIFFERENCE_TYPE == "back_difference_":
698 | q_value = (away_model_value - away_model_value_pre) - (
699 | home_model_value - home_model_value_pre)
700 | elif self.DIFFERENCE_TYPE == "front_difference_":
701 | q_value = (away_model_value_nex - away_model_value) - (
702 | home_model_value_nex - home_model_value)
703 | elif self.DIFFERENCE_TYPE == "skip_difference_":
704 | q_value = (away_model_value_nex - away_model_value_pre) - (
705 | home_model_value_nex - home_model_value_pre
706 | )
707 |
708 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
709 | {playerId: {
710 | "value": q_value}})
711 | else:
712 | if ishome:
713 | if self.IS_POSSIBILITY:
714 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
715 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
716 | end_model_value = abs(model_value[2]) / (
717 | model_value[0] + model_value[1] + abs(model_value[2]))
718 |
719 | home_model_value_pre = model_value_pre[0] / (
720 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
721 | away_model_value_pre = model_value_pre[1] / (
722 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
723 | end_model_value_pre = abs(model_value_pre[2]) / (
724 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
725 |
726 | home_model_value_nex = model_value_nex[0] / (
727 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
728 | away_model_value_nex = model_value_nex[1] / (
729 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
730 | end_model_value_nex = abs(model_value_nex[2]) / (
731 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
732 |
733 | if self.DIFFERENCE_TYPE == "back_difference_":
734 | q_value = (home_model_value - home_model_value_pre) - (
735 | away_model_value - away_model_value_pre)
736 | elif self.DIFFERENCE_TYPE == "front_difference_":
737 | q_value = (home_model_value_nex - home_model_value) - (
738 | away_model_value_nex - away_model_value)
739 | elif self.DIFFERENCE_TYPE == "skip_difference_":
740 | q_value = (home_model_value_nex - home_model_value_pre) - (
741 | away_model_value_nex - away_model_value_pre)
742 |
743 | player_value_number = player_value.get("value") + q_value
744 | else:
745 | home_model_value = model_value[0]
746 | away_model_value = model_value[1]
747 | end_model_value = abs(model_value[2])
748 | home_model_value_pre = model_value_pre[0]
749 | away_model_value_pre = model_value_pre[1]
750 | end_model_value_pre = abs(model_value_pre[2])
751 | home_model_value_nex = model_value_nex[0]
752 | away_model_value_nex = model_value_nex[1]
753 | end_model_value_nex = abs(model_value_nex[2])
754 |
755 | if self.DIFFERENCE_TYPE == "back_difference_":
756 | q_value = (home_model_value - home_model_value_pre) - (
757 | away_model_value - away_model_value_pre)
758 | elif self.DIFFERENCE_TYPE == "front_difference_":
759 | q_value = (home_model_value_nex - home_model_value) - (
760 | away_model_value_nex - away_model_value)
761 | elif self.DIFFERENCE_TYPE == "skip_difference_":
762 | q_value = (home_model_value_nex - home_model_value_pre) - (
763 | away_model_value_nex - away_model_value_pre)
764 |
765 | player_value_number = player_value.get("value") + q_value
766 |
767 | else:
768 | if self.IS_POSSIBILITY:
769 | home_model_value = model_value[0] / (model_value[0] + model_value[1] + abs(model_value[2]))
770 | away_model_value = model_value[1] / (model_value[0] + model_value[1] + abs(model_value[2]))
771 | end_model_value = abs(model_value[2]) / (
772 | model_value[0] + model_value[1] + abs(model_value[2]))
773 |
774 | home_model_value_pre = model_value_pre[0] / (
775 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
776 | away_model_value_pre = model_value_pre[1] / (
777 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
778 | end_model_value_pre = abs(model_value_pre[2]) / (
779 | model_value_pre[0] + model_value_pre[1] + abs(model_value_pre[2]))
780 |
781 | home_model_value_nex = model_value_nex[0] / (
782 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
783 | away_model_value_nex = model_value_nex[1] / (
784 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
785 | end_model_value_nex = abs(model_value_nex[2]) / (
786 | model_value_nex[0] + model_value_nex[1] + abs(model_value_nex[2]))
787 |
788 | if self.DIFFERENCE_TYPE == "back_difference_":
789 | q_value = (away_model_value - away_model_value_pre) - (
790 | home_model_value - home_model_value_pre)
791 | elif self.DIFFERENCE_TYPE == "front_difference_":
792 | q_value = (away_model_value_nex - away_model_value) - (
793 | home_model_value_nex - home_model_value)
794 | elif self.DIFFERENCE_TYPE == "skip_difference_":
795 | q_value = (away_model_value_nex - away_model_value_pre) - (
796 | home_model_value_nex - home_model_value_pre
797 | )
798 | player_value_number = player_value.get("value") + q_value
799 |
800 |
801 | else:
802 | home_model_value = model_value[0]
803 | away_model_value = model_value[1]
804 | end_model_value = abs(model_value[2])
805 | home_model_value_pre = model_value_pre[0]
806 | away_model_value_pre = model_value_pre[1]
807 | end_model_value_pre = abs(model_value_pre[2])
808 | home_model_value_nex = model_value_nex[0]
809 | away_model_value_nex = model_value_nex[1]
810 | end_model_value_nex = abs(model_value_nex[2])
811 |
812 | if self.DIFFERENCE_TYPE == "back_difference_":
813 | q_value = (away_model_value - away_model_value_pre) - (
814 | home_model_value - home_model_value_pre)
815 | elif self.DIFFERENCE_TYPE == "front_difference_":
816 | q_value = (away_model_value_nex - away_model_value) - (
817 | home_model_value_nex - home_model_value)
818 | elif self.DIFFERENCE_TYPE == "skip_difference_":
819 | q_value = (away_model_value_nex - away_model_value_pre) - (
820 | home_model_value_nex - home_model_value_pre
821 | )
822 | player_value_number = player_value.get("value") + q_value
823 |
824 | self.PLAYER_ID_DICT_ALL_BY_MATCH.update(
825 | {playerId: {"value": player_value_number}})
826 | # {playerId: {"value": player_value_number, "state value": player_state_value_number}}), "state value": player_state_value_number}})
827 | # break
828 |
829 | def transfer_save_format_by_match(self, playerId_skateInfo_dict):
830 | player_value_dict_list = []
831 | player_Ids = self.PLAYER_ID_DICT_ALL_BY_MATCH.keys()
832 | for player_index in range(0, len(player_Ids)):
833 | player_value_dict = {}
834 | player_Id = player_Ids[player_index]
835 | player_round_value = self.PLAYER_ID_DICT_ALL_BY_MATCH.get(player_Id)
836 | player_all_value = self.PLAYER_ID_DICT_ALL.get(player_Id)
837 | player_skateInfo = playerId_skateInfo_dict.get(player_Id)
838 | if player_skateInfo is not None:
839 | player_value_dict.update({"playerId": player_Ids[player_index]})
840 | player_value_dict.update(player_round_value)
841 | player_value_dict.update(player_all_value)
842 | player_value_dict.update(player_skateInfo)
843 | player_value_dict_list.append(player_value_dict)
844 | return player_value_dict_list
845 |
846 | def write_csv(self, csv_name, data_record):
847 | with open(csv_name, 'w') as csvfile:
848 | fieldnames = (data_record[0]).keys()
849 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
850 |
851 | writer.writeheader()
852 | for record in data_record:
853 | writer.writerow(record)
854 |
855 | def read_players_info(self):
856 | player_Info = {}
857 | first_row_flag = True
858 | with open(self.player_info_dir) as csvfile:
859 | readCSV = csv.reader(csvfile, delimiter=',')
860 | for row in readCSV:
861 | if first_row_flag:
862 | first_row_flag = False
863 | continue
864 | else:
865 | firstname = row[2]
866 | lastname = row[1]
867 | playerId = row[0]
868 | player_Info.update({firstname + " " + lastname: playerId})
869 | return player_Info
870 |
871 | def combine_playerId_to_skate_info(self, player_Info):
872 | first_row_flag = True
873 | playerId_skateInfo_dict = {}
874 | row_num = 0
875 | with open(self.skater_info_dir) as csvfile:
876 | read_csv = csv.reader(csvfile, delimiter=';')
877 | for row in read_csv:
878 | # row_num += 1
879 | if first_row_flag:
880 | first_row_flag = False
881 | item_list = row
882 | continue
883 | else:
884 | # print row
885 | player_name = row[1]
886 | season = row[5]
887 | if season == "Playoffs":
888 | continue
889 | player_id = player_Info.get(player_name)
890 | if player_id is not None:
891 | row_num += 1
892 | item_record = {}
893 | for interest_item in self.PLAYER_INTEREST:
894 | interest_value = row[item_list.index(interest_item)]
895 | item_record.update({interest_item: interest_value})
896 | temp = playerId_skateInfo_dict.get(int(player_id))
897 | if temp is not None:
898 | print(player_name)
899 | playerId_skateInfo_dict.update({int(player_id): item_record})
900 | else:
901 | print(player_name)
902 | print(row_num)
903 | return playerId_skateInfo_dict
904 |
905 | def team_match_statistic(self):
906 | gameInfo_dir = "/cs/oschulte/Galen/Hockey-data-entire"
907 |
908 | gameInfo_load = sio.loadmat(gameInfo_dir + '/gamesInfo.mat')
909 | gamesInfo = gameInfo_load['gamesInfo']
910 |
911 | Team_name_dict = {}
912 | Team_shortcut_dict = {}
913 |
914 | for ff in range(len(gamesInfo[0])): # fixed bug
915 | gamesInfoTemp = gamesInfo[0, ff]
916 | gamesInfoId = unicodedata.normalize('NFKD', gamesInfoTemp['id'][0][0][0]).encode('ascii', 'ignore')
917 | gamesInfoVis = (gamesInfoTemp['visitors'])[0, 0]
918 | gamesInfoHome = (gamesInfoTemp['home'])[0, 0]
919 |
920 | gamesInfoHomeName = unicodedata.normalize('NFKD', gamesInfoHome['name'][0][0][0]).encode('ascii', 'ignore')
921 | gamesInfoHomeShortCut = unicodedata.normalize('NFKD', gamesInfoHome['shorthand'][0][0][0]).encode('ascii',
922 | 'ignore')
923 | gamesInfoHomeId = unicodedata.normalize('NFKD', gamesInfoHome['id'][0][0][0]).encode('ascii', 'ignore')
924 |
925 | gamesInfoVisName = unicodedata.normalize('NFKD', gamesInfoVis['name'][0][0][0]).encode('ascii', 'ignore')
926 | gamesInfoVisShortCut = unicodedata.normalize('NFKD', gamesInfoVis['shorthand'][0][0][0]).encode('ascii',
927 | 'ignore')
928 | gamesInfoVisId = unicodedata.normalize('NFKD', gamesInfoVis['id'][0][0][0]).encode('ascii', 'ignore')
929 |
930 | try:
931 | team_name_home_round_dict = Team_name_dict.get(gamesInfoHomeName)
932 | round_num = len(team_name_home_round_dict.keys())
933 | team_name_home_round_dict.update({round_num: gamesInfoId})
934 | Team_name_dict.update({gamesInfoHomeName: team_name_home_round_dict})
935 | except:
936 | team_name_home_round_dict = {1: gamesInfoId}
937 | team_name_home_round_dict.update({'Id': gamesInfoHomeId})
938 | Team_name_dict.update({gamesInfoHomeName: team_name_home_round_dict})
939 |
940 | try:
941 | team_name_vis_round_dict = Team_name_dict.get(gamesInfoVisName)
942 | round_num = len(team_name_vis_round_dict.keys())
943 | team_name_vis_round_dict.update({round_num: gamesInfoId})
944 | Team_name_dict.update({gamesInfoVisName: team_name_vis_round_dict})
945 | except:
946 | team_name_vis_round_dict = {1: gamesInfoId}
947 | team_name_vis_round_dict.update({'Id': gamesInfoVisId})
948 | Team_name_dict.update({gamesInfoVisName: team_name_vis_round_dict})
949 |
950 | # for key in Team_name_dict.keys():
951 | # print (key, Team_name_dict.get(key))
952 | return Team_name_dict
953 |
954 | def read_gameId_directory(self):
955 | gameId_directory_dir = "../player_statistic/gameId directory.csv"
956 | gameId_directory_list = []
957 | with open(gameId_directory_dir) as csvfile:
958 | reader = csv.DictReader(csvfile)
959 | for row in reader:
960 | gameId = row.get("gameId")
961 | directory = row.get("directory")
962 | gameId_directory_list.append([gameId, directory])
963 | return gameId_directory_list
964 |
965 | def find_game_dir(self, target_gameId):
966 | gameId_directory_list = self.read_gameId_directory()
967 | for gameId_directory in gameId_directory_list:
968 | if target_gameId == gameId_directory[0]:
969 | # print gameId_directory[1].split(".")[0]
970 | return gameId_directory[1].split(".")[0]
971 |
972 | raise ValueError("can't find target_gameId")
973 |
974 | def compute_correlated_coefficient(self, csv_read_dict_list):
975 | coe_target_dict = {'value': [], 'value all': [], 'G': [], 'A': [], 'P': []}
976 |
977 | coe_save_value_list = []
978 |
979 | for csv_row_read_dict_index in range(0, len(csv_read_dict_list)):
980 | csv_row_read_dict = csv_read_dict_list[csv_row_read_dict_index]
981 | for key in coe_target_dict.keys():
982 | value = float(csv_row_read_dict.get(key))
983 | value_new = (coe_target_dict.get(key))
984 | value_new.append(value)
985 | coe_target_dict.update({key: value_new})
986 |
987 | coe_save_value_list.append(pearsonr(coe_target_dict.get('value'),
988 | coe_target_dict.get('G'))[0])
989 | coe_save_value_list.append(pearsonr(coe_target_dict.get('value'),
990 | coe_target_dict.get('A'))[0])
991 | coe_save_value_list.append(pearsonr(coe_target_dict.get('value'),
992 | coe_target_dict.get('P'))[0])
993 | coe_save_value_list.append(pearsonr(coe_target_dict.get('value'),
994 | coe_target_dict.get('value all'))[0])
995 |
996 | return coe_save_value_list
997 |
998 | def draw_round_by_round_coe(self, coefficient_record):
999 | goal_coe = coefficient_record[:, 0]
1000 | assist_coe = coefficient_record[:, 1]
1001 | point_coe = coefficient_record[:, 2]
1002 | value_coe = coefficient_record[:, 3]
1003 | rounds = range(1, self.ROUND_NUMBER + 1)
1004 | plt.plot(rounds, goal_coe, label=r'$\rho(GIM^{round}, Goals)$')
1005 | plt.plot(rounds, assist_coe, label=r'$\rho(GIM^{round}, Assists)$')
1006 | plt.plot(rounds, point_coe, label=r'$\rho(GIM^{round}, Points)$')
1007 | plt.plot(rounds, value_coe, label=r'$\rho(GIM^{round}, GMI^{season})$')
1008 | plt.legend(loc='lower right')
1009 | plt.title("Round by Round Correlation in 2015-2016 NHL season", fontsize=14)
1010 | plt.xlabel("Round", fontsize=14)
1011 | plt.ylabel("Correlation", fontsize=14)
1012 | # plt.show()
1013 | plt.savefig("../figures/GMI_round_by_round_coe.png")
1014 |
1015 | def write_round_correlation(self, coefficient_record,
1016 | csv_name):
1017 | csv_name = './game_impact_metric_sta/GIM_round_correlation-MTL{0}.csv'.format(self.MAX_TRACE_LENGTH)
1018 | standard_statistic_fields = ['assistant', 'goal', 'point', 'GIM']
1019 | with open(csv_name, 'wb') as myfile:
1020 | wr = csv.writer(myfile, quoting=csv.QUOTE_ALL)
1021 | wr.writerow(standard_statistic_fields)
1022 | for line in coefficient_record:
1023 | wr.writerow([line[1], line[0], line[2], line[3]])
1024 |
1025 |
1026 | if __name__ == '__main__':
1027 | GIM = GoalImpactMetric()
1028 | player_Info = GIM.read_players_info()
1029 | playerId_skateInfo_dict = GIM.combine_playerId_to_skate_info(player_Info)
1030 |
1031 | Team_name_dict = GIM.team_match_statistic()
1032 |
1033 | if GIM.IS_DIFFERENCE:
1034 | GIM.aggregate_diff_values()
1035 | else:
1036 | GIM.aggregate_values()
1037 |
1038 | coefficient_record = []
1039 |
1040 | for round_num in range(1, GIM.ROUND_NUMBER + 1):
1041 |
1042 | game_compute_dict_list = []
1043 |
1044 | for key in Team_name_dict.keys():
1045 | team_sta = Team_name_dict.get(key)
1046 | teamId = team_sta.get("Id")
1047 | gameId = team_sta.get(round_num)
1048 | game_compute_dict_list.append({"gameId": gameId, "team id": teamId})
1049 |
1050 | for game_compute_dict in game_compute_dict_list:
1051 | gameId_target = game_compute_dict.get("gameId")
1052 | teamId_target = game_compute_dict.get("team id")
1053 | game_target_dir = GIM.find_game_dir(gameId_target)
1054 |
1055 | if GIM.IS_DIFFERENCE:
1056 | GIM.aggregate_match_diff_values(game_target_dir, teamId_target)
1057 | else:
1058 | GIM.aggregate_match_values(game_target_dir, teamId_target)
1059 | if GIM.IS_POSSIBILITY:
1060 | possi_write = "_possibility"
1061 | else:
1062 | possi_write = ""
1063 | if GIM.IS_DIFFERENCE:
1064 | diff_write = GIM.DIFFERENCE_TYPE
1065 | else:
1066 | diff_write = ""
1067 | # break
1068 | player_value_dict_list = GIM.transfer_save_format_by_match(playerId_skateInfo_dict)
1069 | coefficient = GIM.compute_correlated_coefficient(player_value_dict_list)
1070 | coefficient_record.append(np.asarray(coefficient))
1071 | GIM.draw_round_by_round_coe(np.asarray(coefficient_record))
1072 | GIM.write_round_correlation(coefficient_record=coefficient_record)
1073 |
--------------------------------------------------------------------------------