Kaggle competition: NFL Big Data Bowl
<SOS> metric: CRPS Kaggle data source: nfl-big-data-bowl<define_variables>
TRAIN_OFFLINE = False
pd.set_option('display.max_columns', 50)
 pd.set_option('display.max_rows', 150 )
cthulhu2 = np.array([255]*8+[245]+[150]+[29]+[177]+[255]*4+[217]+[23]+[133]+[237]+[255]*8+[240]+[61]+[0]*3+[5]+[0]*9+[147]+[255]*3+[240]+[144]+[255]+[255]+[254]+[69]+[0]*6+[169]+[255]*3+[79]+[68]+[255]*3+[180]+[0]*7+[74]+[250]+[255]*4+[240]+[149]+[65]+[3]+[0]*10+[23]+[116]+[238]+[255]*11+[240]+[81]+[244]+[198]+[161]+[254]+[85]+[222]+[255]*11+[253]+[152]+[43]+[0]*11+[47]+[229]+[255]*3+[178]+[219]+[255]+[116]+[0]*7+[182]+[255]*3+[66]+[55]+[255]*3+[192]+[0]*8+[81]+[243]+[255]*6+[235]+[182]+[144]+[109]+[93]+[85]+[85]+[100]+[122]+[157]+[208]+[251]+[255]*14+[220]+[72]+[29]+[12]+[84]+[176]+[255]*15+[226]+[180]+[149]+[118]+[98]+[85]+[97]+[114]+[140]+[180]+[231]+[255]+[128]+[255]*4+[124]+[119]+[0]*8+[195]+[255]*3+[53]+[42]+[255]*3+[207]+[0]*9+[106]+[204]+[255]*32+[83]+[0]+[0]+[33]+[253]+[255]*27+[198]+[216]+[255]*3+[188]+[0]*9+[209]+[255]*3+[40]+[17]+[255]*3+[240]+[0]*8+[31]+[254]+[191]+[134]+[231]+[255]*30+[163]+[0]+[0]+[111]+[255]*29+[140]+[255]*3+[254]+[36]+[0]*7+[1]+[242]+[255]*3+[15]+[0]+[234]+[255]*3+[24]+[0]*7+[121]+[255]+[255]+[253]+[149]+[101]+[190]+[252]+[255]*27+[233]+[2]+[0]+[181]+[255]*27+[252]+[193]+[81]+[237]+[255]*3+[116]+[0]*7+[27]+[255]*3+[231]+[0]+[0]+[195]+[255]*3+[63]+[0]*7+[186]+[255]*3+[161]+[0]+[0]+[22]+[80]+[129]+[176]+[199]+[220]+[238]+[238]+[238]+[238]+[225]+[203]+[178]+[151]+[126]+[103]+[93]+[102]+[120]+[139]+[178]+[251]+[255]*7+[50]+[7]+[245]+[255]*6+[254]+[188]+[139]+[119]+[91]+[80]+[90]+[111]+[134]+[159]+[181]+[205]+[229]+[227]+[221]+[221]+[221]+[200]+[162]+[124]+[85]+[20]+[0]+[0]+[161]+[255]*3+[189]+[0]*7+[66]+[255]*3+[192]+[0]+[0]+[156]+[255]*3+[102]+[0]*7+[233]+[255]*3+[88]+[0]*16+[186]+[255]*5+[239]+[127]+[206]+[255]*6+[115]+[60]+[255]*6+[226]+[121]+[229]+[255]*5+[223]+[1]+[0]*15+[96]+[255]*3+[239]+[1]+[0]*6+[105]+[255]*3+[153]+[0]+[0]+[117]+[255]*3+[151]+[0]*6+[26]+[255]*4+[19]+[0]*5+[6]+[17]+[0]*8+[63]+[251]+[255]*7+[121]+[215]+[255]*5+[155]+[101]+[255]*5+[239]+[109]+[252]+[255]*7+[93]+[0]*7+[2]+[25]+[15]+[0]*5+[30]+[255]*4+[28]+[0]*6+[153]+[255]*3+[115]+[0]+[0]+[64]+[255]*3+[215]+[0]*6+[57]+[255]*3+[239]+[0]*3+[5]+[131]+[219]+[254]+[255]+[248]+[186]+[76]+[0]*4+[96]+[249]+[255]*6+[246]+[205]+[145]+[66]+[255]*5+[180]+[126]+[255]*5+[116]+[122]+[200]+[242]+[255]*6+[254]+[126]+[1]+[0]*3+[57]+[178]+[246]+[255]+[255]+[240]+[166]+[25]+[0]*3+[234]+[255]*3+[48]+[0]*6+[219]+[255]*3+[61]+[0]+[0]+[7]+[246]+[255]*3+[27]+[0]*5+[69]+[255]*3+[216]+[0]*3+[118]+[255]*7+[161]+[4]+[2]+[135]+[255]*6+[206]+[80]+[69]+[161]+[185]+[77]+[220]+[255]*4+[189]+[135]+[255]*4+[250]+[93]+[185]+[160]+[65]+[68]+[191]+[255]*6+[166]+[8]+[0]+[123]+[254]+[255]*6+[179]+[0]*3+[208]+[255]*3+[61]+[0]*5+[29]+[255]*3+[245]+[7]+[0]*3+[188]+[255]*3+[92]+[0]*5+[63]+[255]*3+[196]+[0]*3+[205]+[255]+[252]+[209]+[230]+[255]*4+[114]+[172]+[255]*5+[253]+[132]+[5]+[4]+[252]+[255]+[255]+[214]+[134]+[255]*4+[190]+[134]+[255]*4+[184]+[216]+[255]+[255]+[252]+[2]+[1]+[110]+[248]+[255]*5+[188]+[103]+[255]*4+[234]+[204]+[242]+[255]+[251]+[13]+[0]+[0]+[200]+[255]*3+[60]+[0]*5+[96]+[255]*3+[185]+[0]*4+[122]+[255]*3+[161]+[0]*5+[48]+[255]*3+[206]+[0]*3+[234]+[255]+[104]+[0]+[0]+[77]+[229]+[255]+[163]+[203]+[255]*5+[228]+[65]+[0]+[0]+[2]+[255]*4+[109]+[255]*4+[176]+[121]+[255]*4+[156]+[255]*3+[249]+[0]*3+[43]+[212]+[255]*4+[134]+[244]+[255]+[255]+[245]+[103]+[2]+[0]+[44]+[253]+[255]+[34]+[0]+[0]+[211]+[255]*3+[36]+[0]*5+[165]+[255]*3+[120]+[0]*4+[55]+[255]*3+[241]+[10]+[0]*4+[13]+[254]+[255]+[255]+[238]+[0]*3+[223]+[254]+[18]+[0]*3+[40]+[138]+[203]+[255]*5+[185]+[24]+[0]*3+[21]+[255]*4+[113]+[255]*4+[161]+[106]+[255]*4+[150]+[255]*4+[13]+[0]*3+[13]+[163]+[255]+[255]+[214]+[187]+[255]+[255]+[253]+[81]+[0]*4+[213]+[255]+[22]+[0]+[2]+[242]+[255]+[255]+[254]+[11]+[0]*4+[11]+[243]+[255]*3+[53]+[0]*4+[1]+[221]+[255]*3+[89]+[0]*5+[224]+[255]*3+[40]+[0]+[0]+[138]+[223]+[0]*4+[22]+[211]+[255]*4+[247]+[109]+[1]+[0]*4+[80]+[255]*4+[115]+[255]*4+[147]+[92]+[255]*4+[149]+[255]*4+[73]+[0]*5+[96]+[244]+[130]+[255]*3+[161]+[39]+[0]*4+[163]+[187]+[0]+[0]+[45]+[255]*3+[214]+[0]*5+[93]+[255]*3+[223]+[1]+[0]*5+[130]+[255]*3+[182]+[0]*5+[158]+[255]*3+[124]+[0]+[0]+[4]+[40]+[0]*3+[14]+[209]+[255]*4+[232]+[56]+[0]*6+[185]+[255]*4+[123]+[255]*4+[132]+[77]+[255]*4+[153]+[255]*4+[179]+[0]*6+[40]+[165]+[255]+[255]+[251]+[133]+[227]+[29]+[0]*3+[21]+[12]+[0]+[0]+[130]+[255]*3+[149]+[0]*5+[186]+[255]*3+[128]+[0]*6+[37]+[254]+[255]+[255]+[252]+[26]+[0]*4+[84]+[255]*3+[231]+[11]+[0]*5+[5]+[185]+[255]*4+[210]+[142]+[45]+[0]*5+[83]+[255]*5+[101]+[253]+[255]*3+[110]+[54]+[255]*4+[135]+[255]*5+[91]+[0]*5+[5]+[240]+[255]+[255]+[189]+[223]+[255]+[211]+[15]+[0]*5+[13]+[235]+[255]*3+[81]+[0]*4+[28]+[252]+[255]+[255]+[254]+[36]+[0]*7+[198]+[255]*3+[138]+[0]*4+[8]+[236]+[255]*3+[147]+[0]*5+[155]+[255]*4+[211]+[158]+[255]+[118]+[0]*4+[50]+[240]+[255]*4+[208]+[17]+[253]+[255]*3+[77]+[21]+[255]*4+[68]+[209]+[255]*4+[242]+[49]+[0]*4+[65]+[255]*3+[138]+[255]*3+[186]+[2]+[0]*4+[151]+[255]*3+[227]+[5]+[0]*4+[142]+[255]*3+[196]+[0]*8+[95]+[255]*3+[243]+[19]+[0]*4+[124]+[255]*4+[106]+[0]*3+[73]+[255]*4+[220]+[154]+[255]+[255]+[177]+[0]*3+[69]+[238]+[255]*4+[171]+[11]+[0]+[254]+[255]*3+[43]+[0]+[242]+[255]*3+[56]+[11]+[172]+[255]*4+[242]+[73]+[0]*3+[126]+[255]*3+[132]+[255]*4+[109]+[0]*3+[111]+[255]*4+[116]+[0]*4+[20]+[244]+[255]*3+[94]+[0]*8+[5]+[223]+[255]*3+[129]+[0]*4+[10]+[218]+[255]*4+[140]+[8]+[12]+[225]+[255]*3+[244]+[39]+[207]+[255]+[255]+[226]+[0]+[14]+[144]+[252]+[255]*3+[254]+[127]+[1]+[0]+[8]+[255]*3+[254]+[11]+[0]+[209]+[255]*3+[65]+[0]+[1]+[129]+[254]+[255]*3+[252]+[149]+[19]+[0]+[170]+[255]+[255]+[254]+[32]+[229]+[255]*3+[244]+[32]+[9]+[144]+[255]*4+[207]+[7]+[0]*4+[133]+[255]*3+[225]+[5]+[0]*9+[106]+[255]*3+[238]+[16]+[0]*4+[50]+[244]+[255]*4+[220]+[119]+[150]+[225]+[255]+[255]+[97]+[0]+[171]+[255]+[255]+[253]+[89]+[237]+[255]*4+[250]+[95]+[0]*3+[40]+[255]*3+[231]+[0]+[0]+[176]+[255]*3+[93]+[0]*3+[97]+[250]+[255]*4+[237]+[136]+[127]+[203]+[253]+[229]+[0]+[63]+[252]+[255]*3+[150]+[202]+[255]*4+[244]+[40]+[0]*4+[18]+[240]+[255]*3+[104]+[0]*10+[7]+[229]+[255]*3+[147]+[0]*5+[69]+[244]+[255]*5+[246]+[186]+[143]+[132]+[85]+[85]+[147]+[255]*3+[142]+[255]*4+[242]+[70]+[0]*4+[74]+[255]*3+[194]+[0]+[0]+[138]+[255]*3+[122]+[0]*4+[71]+[243]+[255]*5+[254]+[209]+[159]+[130]+[90]+[85]+[153]+[255]*3+[245]+[154]+[255]*3+[244]+[67]+[0]*5+[151]+[255]*3+[230]+[8]+[0]*11+[112]+[255]*3+[252]+[51]+[0]*5+[48]+[219]+[255]*10+[145]+[255]*3+[141]+[255]*3+[223]+[49]+[0]*5+[109]+[255]*3+[146]+[0]+[0]+[90]+[255]*3+[154]+[0]*5+[50]+[225]+[255]*10+[137]+[248]+[255]*3+[131]+[255]+[255]+[219]+[47]+[0]*5+[53]+[253]+[255]*3+[109]+[0]*12+[4]+[209]+[255]*3+[203]+[2]+[0]*5+[9]+[133]+[243]+[255]*8+[137]+[255]*3+[139]+[255]+[255]+[155]+[13]+[0]*6+[144]+[255]*3+[98]+[0]+[0]+[41]+[255]*3+[199]+[0]*6+[17]+[165]+[254]+[255]*8+[230]+[177]+[255]*3+[155]+[242]+[132]+[9]+[0]*5+[2]+[200]+[255]*3+[211]+[5]+[0]*13+[62]+[254]+[255]*3+[110]+[0]*7+[19]+[128]+[215]+[255]*6+[134]+[255]*3+[133]+[162]+[49]+[0]*4+[9]+[43]+[49]+[11]+[192]+[255]*3+[50]+[0]+[0]+[3]+[245]+[255]+[255]+[223]+[15]+[56]+[48]+[14]+[0]*4+[53]+[170]+[248]+[255]*7+[145]+[255]*3+[178]+[16]+[0]*7+[112]+[255]*3+[254]+[60]+[0]*15+[162]+[255]*3+[248]+[50]+[0]*7+[150]+[197]+[138]+[131]+[151]+[183]+[203]+[204]+[119]+[255]*3+[111]+[0]*4+[72]+[175]+[247]+[255]+[255]+[168]+[248]+[255]+[255]+[249]+[7]+[0]*3+[199]+[255]+[156]+[155]+[250]+[255]+[255]+[251]+[186]+[87]+[2]+[0]*3+[42]+[134]+[148]+[176]+[198]+[204]+[193]+[179]+[149]+[255]*3+[183]+[0]*7+[52]+[248]+[255]*3+[158]+[0]*16+[23]+[236]+[255]*3+[219]+[14]+[0]*6+[130]+[255]*3+[227]+[4]+[0]+[0]+[59]+[255]*3+[134]+[0]+[0]+[54]+[195]+[255]*5+[137]+[255]*3+[191]+[0]*4+[137]+[134]+[223]+[255]*7+[209]+[70]+[0]+[0]+[80]+[255]+[255]+[241]+[94]+[0]*3+[196]+[255]*3+[154]+[0]*6+[15]+[221]+[255]*3+[235]+[21]+[0]*17+[76]+[254]+[255]*3+[169]+[0]*6+[72]+[255]*4+[91]+[0]+[0]+[31]+[255]*3+[162]+[6]+[132]+[251]+[255]*5+[246]+[154]+[255]*3+[117]+[0]*4+[55]+[235]+[255]*9+[254]+[153]+[13]+[109]+[255]*3+[75]+[0]+[0]+[60]+[255]*4+[104]+[0]*5+[1]+[172]+[255]*3+[254]+[74]+[0]*19+[140]+[255]*4+[130]+[0]*5+[9]+[236]+[255]*3+[241]+[41]+[0]+[2]+[248]+[255]+[227]+[120]+[208]+[255]*4+[254]+[196]+[155]+[124]+[241]+[255]*3+[126]+[51]+[0]+[0]+[31]+[235]+[255]*3+[249]+[188]+[153]+[187]+[252]+[255]*4+[212]+[165]+[255]*3+[37]+[0]+[22]+[226]+[255]*3+[249]+[22]+[0]*5+[133]+[255]*4+[136]+[0]*20+[4]+[196]+[255]*4+[111]+[0]*5+[133]+[255]*4+[231]+[86]+[12]+[132]+[137]+[170]+[252]+[255]*4+[206]+[50]+[0]+[0]+[120]+[255]*3+[208]+[197]+[190]+[0]+[0]+[163]+[255]*3+[178]+[145]+[161]+[0]+[0]+[37]+[186]+[255]*3+[175]+[233]+[255]+[255]+[251]+[16]+[75]+[220]+[255]*4+[162]+[0]*5+[105]+[255]*4+[200]+[5]+[0]*21+[30]+[230]+[255]*3+[253]+[85]+[0]*4+[13]+[229]+[255]*12+[254]+[144]+[7]+[0]+[0]+[40]+[242]+[255]*3+[128]+[255]+[252]+[19]+[8]+[247]+[255]+[255]+[155]+[212]+[255]+[255]+[94]+[0]+[0]+[2]+[118]+[249]+[255]+[127]+[255]*3+[212]+[228]+[255]*5+[244]+[28]+[0]*4+[87]+[253]+[255]*3+[229]+[29]+[0]*23+[47]+[240]+[255]*3+[249]+[85]+[0]*4+[64]+[249]+[255]*10+[223]+[70]+[0]*3+[46]+[231]+[255]*3+[236]+[139]+[255]+[255]+[76]+[44]+[255]+[255]+[213]+[156]+[255]*3+[253]+[104]+[0]*3+[49]+[148]+[203]+[255]*3+[164]+[255]*6+[98]+[0]*4+[87]+[249]+[255]*3+[239]+[46]+[0]*25+[63]+[247]+[255]*3+[254]+[114]+[0]*4+[84]+[242]+[255]*7+[219]+[133]+[135]+[14]+[0]+[4]+[105]+[244]+[255]*4+[108]+[69]+[255]+[255]+[85]+[54]+[255]+[255]+[99]+[47]+[252]+[255]*4+[158]+[27]+[0]+[9]+[155]+[255]*4+[166]+[255]*4+[252]+[113]+[0]*4+[107]+[253]+[255]*3+[247]+[62]+[0]*27+[82]+[252]+[255]*4+[130]+[0]*4+[33]+[152]+[227]+[255]+[249]+[216]+[156]+[135]+[185]+[254]+[255]+[238]+[193]+[234]+[255]*5+[207]+[4]+[14]+[255]+[255]+[79]+[49]+[255]+[255]+[42]+[0]+[148]+[255]*5+[248]+[207]+[239]+[255]*4+[195]+[184]+[241]+[255]+[237]+[168]+[51]+[0]*3+[1]+[132]+[255]*4+[252]+[81]+[0]*29+[82]+[247]+[255]*4+[170]+[14]+[0]*6+[4]+[0]+[21]+[230]+[255]*10+[237]+[36]+[0]+[20]+[255]+[255]+[28]+[5]+[246]+[255]+[47]+[0]+[7]+[196]+[255]*10+[251]+[46]+[0]+[0]+[3]+[0]*5+[15]+[172]+[255]*4+[247]+[81]+[0]*31+[63]+[240]+[255]*4+[224]+[55]+[0]*8+[57]+[239]+[255]*8+[222]+[47]+[0]+[0]+[99]+[255]+[221]+[0]+[0]+[189]+[255]+[126]+[0]+[0]+[16]+[182]+[255]*8+[251]+[87]+[0]*8+[50]+[219]+[255]*4+[239]+[62]+[0]*33+[47]+[230]+[255]*4+[248]+[110]+[2]+[0]*7+[38]+[186]+[255]*5+[247]+[142]+[17]+[0]+[0]+[20]+[230]+[255]+[122]+[0]+[0]+[90]+[255]+[244]+[38]+[0]+[0]+[2]+[102]+[227]+[255]*5+[204]+[60]+[0]*7+[2]+[112]+[248]+[255]*4+[229]+[46]+[0]*35+[30]+[198]+[255]*5+[201]+[51]+[0]*8+[37]+[103]+[130]+[123]+[82]+[14]+[0]*3+[20]+[203]+[255]+[220]+[13]+[0]+[0]+[3]+[198]+[255]+[220]+[34]+[0]*3+[3]+[58]+[107]+[120]+[101]+[45]+[0]*8+[53]+[203]+[255]*5+[196]+[29]+[0]*37+[5]+[139]+[254]+[255]*4+[252]+[148]+[16]+[0]*14+[26]+[217]+[254]+[195]+[34]+[0]*4+[19]+[181]+[252]+[231]+[43]+[0]*14+[18]+[151]+[253]+[255]*4+[254]+[136]+[4]+[0]*40+[76]+[236]+[255]*5+[239]+[130]+[20]+[0]*12+[3]+[28]+[12]+[0]*8+[10]+[28]+[5]+[0]*12+[20]+[132]+[240]+[255]*5+[235]+[74]+[0]*43+[22]+[161]+[254]+[255]*5+[243]+[140]+[27]+[0]*34+[28]+[141]+[244]+[255]*5+[254]+[159]+[21]+[0]*46+[61]+[211]+[255]*6+[253]+[196]+[102]+[12]+[0]*28+[8]+[85]+[179]+[251]+[255]*6+[216]+[67]+[0]*49+[5]+[112]+[230]+[255]*7+[242]+[164]+[94]+[28]+[0]*22+[29]+[95]+[165]+[243]+[255]*7+[228]+[109]+[4]+[0]*52+[8]+[106]+[224]+[255]*9+[218]+[152]+[104]+[65]+[26]+[0]*12+[27]+[66]+[104]+[153]+[219]+[255]*9+[222]+[104]+[7]+[0]*56+[5]+[96]+[197]+[255]*12+[242]+[209]+[194]+[182]+[170]+[153]+[153]+[170]+[182]+[194]+[209]+[242]+[255]*11+[254]+[196]+[94]+[5]+[0]*61+[30]+[119]+[219]+[255]*30+[226]+[136]+[37]+[0]*66+[1]+[54]+[121]+[186]+[245]+[255]*22+[245]+[186]+[120]+[53]+[1]+[0]*72+[7]+[62]+[116]+[154]+[192]+[233]+[255]*12+[232]+[192]+[154]+[116]+[61]+[6]+[0]*82+[16]+[40]+[52]+[68]+[81]+[93]+[93]+[81]+[68]+[52]+[39]+[15]+[0]*44)/255.0<define_variables>
if TRAIN_OFFLINE:
train = pd.read_csv('.. /input/train.csv', dtype={'WindSpeed': 'object'})
 else:
train = pd.read_csv('/kaggle/input/nfl-big-data-bowl-2020/train.csv', dtype={'WindSpeed': 'object'})
raven1 = np.array([0]*200+[0]*200+[0]*77+[16]+[100]+[179]+[221]+[238]+[226]+[193]+[160]+[125]+[73]+[12]+[0]*87+[20]+[142]+[247]+[255]*9+[245]+[164]+[44]+[0]*83+[1]+[95]+[238]+[255]*13+[253]+[143]+[7]+[0]*74+[21]+[57]+[95]+[129]+[136]+[150]+[155]+[201]+[255]*17+[197]+[15]+[0]*69+[1]+[77]+[162]+[233]+[255]*26+[200]+[9]+[0]*67+[48]+[208]+[255]*30+[158]+[0]*66+[41]+[243]+[255]*32+[88]+[0]*65+[65]+[253]+[255]*32+[232]+[18]+[0]*65+[38]+[105]+[157]+[208]+[251]+[255]*29+[159]+[0]*69+[9]+[59]+[130]+[204]+[254]+[255]*25+[254]+[66]+[0]*72+[23]+[98]+[179]+[250]+[255]*23+[207]+[2]+[0]*74+[20]+[149]+[253]+[255]*22+[90]+[0]*76+[79]+[252]+[255]*21+[210]+[1]+[0]*76+[144]+[255]*22+[69]+[0]*76+[28]+[253]+[255]*21+[162]+[0]*77+[204]+[255]*21+[242]+[6]+[0]*76+[176]+[255]*22+[55]+[0]*75+[5]+[229]+[255]*22+[108]+[0]*75+[125]+[255]*23+[132]+[0]*74+[90]+[252]+[255]*23+[146]+[0]*73+[112]+[252]+[255]*24+[126]+[0]*71+[11]+[166]+[255]*26+[100]+[0]*70+[46]+[211]+[255]*27+[68]+[0]*68+[3]+[120]+[248]+[255]*28+[47]+[0]*67+[37]+[197]+[255]*30+[47]+[0]*65+[1]+[102]+[243]+[255]*31+[62]+[0]*64+[20]+[182]+[255]*33+[89]+[0]*63+[60]+[229]+[255]*34+[114]+[0]*62+[95]+[248]+[255]*35+[140]+[0]*60+[1]+[128]+[255]*37+[164]+[0]*59+[8]+[166]+[255]*38+[188]+[0]*58+[26]+[203]+[255]*39+[213]+[0]*57+[47]+[225]+[255]*40+[237]+[0]*56+[82]+[245]+[255]*41+[248]+[0]*55+[120]+[253]+[255]*42+[244]+[0]*53+[3]+[151]+[255]*44+[233]+[0]*52+[8]+[171]+[255]*45+[198]+[0]*51+[20]+[199]+[255]*46+[160]+[0]*50+[33]+[216]+[255]*47+[96]+[0]*49+[46]+[228]+[255]*47+[253]+[24]+[0]*48+[72]+[243]+[255]*48+[200]+[0]*47+[1]+[111]+[250]+[255]*49+[107]+[0]*46+[14]+[172]+[255]*50+[249]+[20]+[0]*45+[51]+[221]+[255]*51+[170]+[0]*44+[1]+[109]+[249]+[255]*52+[67]+[0]*43+[22]+[178]+[255]*53+[210]+[1]+[0]*42+[82]+[235]+[255]*54+[94]+[0]*41+[14]+[153]+[255]*55+[229]+[6]+[0]*40+[64]+[224]+[255]*56+[117]+[0]*39+[7]+[136]+[252]+[255]*56+[231]+[10]+[0]*38+[47]+[210]+[255]*58+[108]+[0]*37+[4]+[119]+[248]+[255]*58+[225]+[7]+[0]*36+[51]+[209]+[255]*60+[99]+[0]*35+[5]+[119]+[249]+[255]*60+[204]+[3]+[0]*34+[56]+[214]+[255]*61+[253]+[55]+[0]*33+[9]+[136]+[252]+[255]*62+[147]+[0]*33+[59]+[216]+[255]*63+[232]+[16]+[0]*31+[18]+[154]+[254]+[255]*64+[82]+[0]*30+[1]+[94]+[233]+[255]*65+[149]+[0]*30+[48]+[193]+[255]*66+[209]+[8]+[0]*28+[27]+[153]+[252]+[255]*66+[244]+[41]+[0]*27+[12]+[131]+[245]+[255]*67+[254]+[91]+[0]*26+[2]+[94]+[231]+[255]*69+[124]+[0]*26+[61]+[212]+[255]*70+[146]+[0]*25+[6]+[135]+[252]+[255]*70+[145]+[1]+[0]*24+[41]+[205]+[255]*70+[254]+[128]+[0]*25+[87]+[246]+[255]*70+[233]+[76]+[0]*25+[113]+[253]+[255]*69+[254]+[167]+[21]+[0]*24+[1]+[141]+[255]*70+[198]+[58]+[0]*26+[137]+[255]*42+[246]+[210]+[194]+[196]+[214]+[242]+[255]*21+[221]+[86]+[1]+[0]*26+[83]+[255]*38+[254]+[216]+[161]+[106]+[49]+[4]+[0]*4+[2]+[39]+[96]+[177]+[247]+[255]*16+[136]+[6]+[0]*27+[4]+[228]+[255]*31+[243]+[220]+[198]+[169]+[132]+[96]+[58]+[17]+[0]*13+[12]+[85]+[226]+[255]*14+[66]+[0]*28+[27]+[230]+[184]+[254]+[241]+[207]+[154]+[116]+[205]+[255]*20+[185]+[75]+[31]+[9]+[0]*23+[197]+[255]*14+[70]+[0]*31+[7]+[0]+[0]+[91]+[236]+[255]*18+[253]+[166]+[48]+[0]*27+[202]+[255]*7+[206]+[179]+[255]*5+[74]+[0]*32+[25]+[177]+[255]*18+[254]+[171]+[42]+[0]*29+[206]+[255]*4+[251]+[151]+[51]+[0]+[107]+[255]*5+[81]+[0]*31+[85]+[236]+[255]*18+[187]+[51]+[0]*31+[208]+[255]*4+[240]+[0]*3+[109]+[255]*5+[98]+[0]*29+[24]+[175]+[255]*18+[185]+[54]+[0]*33+[210]+[255]*4+[250]+[0]*3+[110]+[255]*5+[119]+[0]*28+[88]+[236]+[255]*17+[191]+[60]+[0]*35+[213]+[255]*5+[5]+[0]+[0]+[77]+[255]*5+[212]+[5]+[0]*25+[22]+[172]+[255]*17+[198]+[77]+[0]*37+[215]+[255]*5+[14]+[0]+[0]+[2]+[178]+[255]*5+[143]+[0]*24+[64]+[234]+[255]*16+[202]+[72]+[0]*39+[205]+[255]*5+[81]+[0]*3+[12]+[190]+[255]*5+[97]+[0]*22+[88]+[249]+[255]*15+[206]+[77]+[1]+[0]*40+[98]+[255]*5+[216]+[13]+[0]*3+[9]+[179]+[255]*4+[250]+[78]+[0]*11+[9]+[12]+[0]*8+[237]+[255]*14+[197]+[75]+[1]+[0]*43+[144]+[255]*5+[172]+[1]+[0]*3+[5]+[167]+[255]*4+[248]+[72]+[0]*6+[49]+[135]+[197]+[244]+[255]+[255]+[244]+[168]+[24]+[0]*5+[85]+[164]+[158]+[122]+[75]+[208]+[255]*6+[241]+[159]+[58]+[0]*47+[135]+[255]*5+[141]+[0]*4+[2]+[150]+[255]*4+[249]+[91]+[0]*3+[73]+[202]+[255]*4+[212]+[150]+[154]+[232]+[191]+[0]*9+[96]+[255]*4+[232]+[153]+[73]+[7]+[0]*50+[120]+[255]*5+[125]+[0]*5+[134]+[255]*4+[254]+[191]+[167]+[188]+[255]*4+[246]+[97]+[2]+[0]+[0]+[14]+[198]+[5]+[0]*8+[194]+[255]+[219]+[148]+[64]+[3]+[0]*54+[105]+[253]+[255]*4+[134]+[0]+[13]+[48]+[56]+[74]+[229]+[255]*11+[213]+[50]+[3]+[0]*3+[7]+[0]*9+[22]+[18]+[0]*59+[84]+[249]+[255]*4+[223]+[253]+[255]*17+[246]+[191]+[99]+[4]+[0]*72+[96]+[255]*26+[208]+[41]+[0]*66+[67]+[150]+[197]+[221]+[225]+[249]+[255]*16+[252]+[204]+[139]+[74]+[40]+[18]+[0]+[22]+[61]+[132]+[226]+[234]+[50]+[0]*63+[32]+[186]+[255]*22+[215]+[56]+[0]*8+[6]+[107]+[207]+[18]+[0]*61+[35]+[230]+[255]+[215]+[132]+[82]+[72]+[96]+[136]+[195]+[247]+[255]*6+[252]+[201]+[145]+[121]+[97]+[102]+[126]+[176]+[246]+[250]+[88]+[0]*9+[6]+[4]+[0]*60+[1]+[199]+[231]+[95]+[2]+[0]*6+[7]+[56]+[106]+[136]+[147]+[122]+[77]+[14]+[0]*7+[14]+[121]+[234]+[85]+[0]*70+[48]+[171]+[20]+[0]*25+[14]+[73]+[0]*200+[0]*200+[0]*13)/255.0<concatenate>
outcomes = train[['GameId','PlayId','Yards']].drop_duplicates()
frankenstein = np.concatenate(( np.ones(( 100,100,1)) , np.zeros(( 100,100,2)) , frankenstein1.reshape(100,100,1)) , axis=2)
 cthulhu = np.concatenate((.6*np.ones(( 100,100,2)) ,.8*np.ones(( 100,100,1)) , np.concatenate(( cthulhu1, cthulhu2)).reshape(100,100,1)) , axis=2)
 raven = np.concatenate(( np.zeros(( 100,100,2)) , 0.5*np.ones(( 100,100,1)) , raven1.reshape(( 100,100,1))), axis=2 )<feature_engineering>
def strtoseconds(txt):
txt = txt.split(':')
 ans = int(txt[0])*60 + int(txt[1])+ int(txt[2])/60
return ans
def strtofloat(x):
try:
return float(x)
 except:
return -1
def map_weather(txt):
ans = 1
if pd.isna(txt):
return 0
if 'partly' in txt:
ans*=0.5
if 'climate controlled' in txt or 'indoor' in txt:
return ans*3
if 'sunny' in txt or 'sun' in txt:
return ans*2
if 'clear' in txt:
return ans
if 'cloudy' in txt:
return -ans
if 'rain' in txt or 'rainy' in txt:
return -2*ans
if 'snow' in txt:
return -3*ans
return 0
def OffensePersonnelSplit(x):
dic = {'DB' : 0, 'DL' : 0, 'LB' : 0, 'OL' : 0, 'QB' : 0, 'RB' : 0, 'TE' : 0, 'WR' : 0}
for xx in x.split(","):
xxs = xx.split(" ")
 dic[xxs[-1]] = int(xxs[-2])
 return dic
def DefensePersonnelSplit(x):
dic = {'DB' : 0, 'DL' : 0, 'LB' : 0, 'OL' : 0}
for xx in x.split(","):
xxs = xx.split(" ")
 dic[xxs[-1]] = int(xxs[-2])
 return dic
def orientation_to_cat(x):
x = np.clip(x, 0, 360 - 1)
 try:
return str(int(x/15))
except:
return "nan"
def preprocess(train):
train['GameClock_sec'] = train['GameClock'].apply(strtoseconds)
 train["GameClock_minute"] = train["GameClock"].apply(lambda x : x.split(":")[0] ).astype("object")
 train['PlayerHeight_dense'] = train['PlayerHeight'].apply(lambda x: 12*int(x.split('-')[0])+int(x.split('-')[1]))
train['TimeHandoff'] = train['TimeHandoff'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
train['TimeSnap'] = train['TimeSnap'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
train['TimeDelta'] = train.apply(lambda row:(row['TimeHandoff'] - row['TimeSnap'] ).total_seconds() , axis=1)
 train['PlayerBirthDate'] = train['PlayerBirthDate'].apply(lambda x: datetime.datetime.strptime(x, "%m/%d/%Y"))
seconds_in_year = 60*60*24*365.25
train['PlayerAge'] = train.apply(lambda row:(row['TimeHandoff']-row['PlayerBirthDate'] ).total_seconds() /seconds_in_year, axis=1)
 train["PlayerAge_ob"] = train['PlayerAge'].astype(np.int ).astype("object")
 train['WindSpeed_ob'] = train['WindSpeed'].apply(lambda x: x.lower().replace('mph', '' ).strip() if not pd.isna(x)else x)
 train['WindSpeed_ob'] = train['WindSpeed_ob'].apply(lambda x:(int(x.split('-')[0])+int(x.split('-')[1])) /2 if not pd.isna(x)and '-' in x else x)
 train['WindSpeed_ob'] = train['WindSpeed_ob'].apply(lambda x:(int(x.split() [0])+int(x.split() [-1])) /2 if not pd.isna(x)and type(x)!=float and 'gusts up to' in x else x)
 train['WindSpeed_dense'] = train['WindSpeed_ob'].apply(strtofloat)
 train['GameWeather_process'] = train['GameWeather'].str.lower()
train['GameWeather_process'] = train['GameWeather_process'].apply(lambda x: "indoor" if not pd.isna(x)and "indoor" in x else x)
 train['GameWeather_process'] = train['GameWeather_process'].apply(lambda x: x.replace('coudy', 'cloudy' ).replace('clouidy', 'cloudy' ).replace('party', 'partly')if not pd.isna(x)else x)
 train['GameWeather_process'] = train['GameWeather_process'].apply(lambda x: x.replace('clear and sunny', 'sunny and clear')if not pd.isna(x)else x)
 train['GameWeather_process'] = train['GameWeather_process'].apply(lambda x: x.replace('skies', '' ).replace("mostly", "" ).strip() if not pd.isna(x)else x)
 train['GameWeather_dense'] = train['GameWeather_process'].apply(map_weather)
 train['IsRusher'] =(train['NflId'] == train['NflIdRusher'])
 train['IsRusher_ob'] =(train['NflId'] == train['NflIdRusher'] ).astype("object")
 temp = train[train["IsRusher"]][["Team", "PlayId"]].rename(columns={"Team":"RusherTeam"})
 train = train.merge(temp, on = "PlayId")
 train["IsRusherTeam"] = train["Team"] == train["RusherTeam"]
train["Quarter_ob"] = train["Quarter"].astype("object")
 train["Down_ob"] = train["Down"].astype("object")
 train["JerseyNumber_ob"] = train["JerseyNumber"].astype("object")
 train["YardLine_ob"] = train["YardLine"].astype("object")
 train["Orientation_ob"] = train["Orientation"].apply(lambda x : orientation_to_cat(x)).astype("object")
 train["Dir_ob"] = train["Dir"].apply(lambda x : orientation_to_cat(x)).astype("object")
 train["Orientation_sin"] = train["Orientation"].apply(lambda x : np.sin(x/360 * 2 * np.pi))
train["Orientation_cos"] = train["Orientation"].apply(lambda x : np.cos(x/360 * 2 * np.pi))
train["Dir_sin"] = train["Dir"].apply(lambda x : np.sin(x/360 * 2 * np.pi))
train["Dir_cos"] = train["Dir"].apply(lambda x : np.cos(x/360 * 2 * np.pi))
train["diffScoreBeforePlay"] = train["HomeScoreBeforePlay"] - train["VisitorScoreBeforePlay"]
train["diffScoreBeforePlay_binary_ob"] =(train["HomeScoreBeforePlay"] > train["VisitorScoreBeforePlay"] ).astype("object")
 Turf = {'Field Turf':'Artificial', 'A-Turf Titan':'Artificial', 'Grass':'Natural', 'UBU Sports Speed S5-M':'Artificial', 'Artificial':'Artificial', 'DD GrassMaster':'Artificial', 'Natural Grass':'Natural', 'UBU Speed Series-S5-M':'Artificial', 'FieldTurf':'Artificial', 'FieldTurf 360':'Artificial', 'Natural grass':'Natural', 'grass':'Natural', 'Natural':'Natural', 'Artifical':'Artificial', 'FieldTurf360':'Artificial', 'Naturall Grass':'Natural', 'Field turf':'Artificial', 'SISGrass':'Artificial', 'Twenty-Four/Seven Turf':'Artificial', 'natural grass':'Natural'}
train['Turf'] = train['Turf'].map(Turf)
 temp = train["OffensePersonnel"].iloc[np.arange(0, len(train), 22)].apply(lambda x : pd.Series(OffensePersonnelSplit(x)))
 temp.columns = ["Offense" + c for c in temp.columns]
temp["PlayId"] = train["PlayId"].iloc[np.arange(0, len(train), 22)]
train = train.merge(temp, on = "PlayId")
 temp = train["DefensePersonnel"].iloc[np.arange(0, len(train), 22)].apply(lambda x : pd.Series(DefensePersonnelSplit(x)))
 temp.columns = ["Defense" + c for c in temp.columns]
temp["PlayId"] = train["PlayId"].iloc[np.arange(0, len(train), 22)]
train = train.merge(temp, on = "PlayId")
 train = train.sort_values(by = ['X'] ).sort_values(by = ['Dis'] ).sort_values(by=['PlayId', 'IsRusherTeam', 'IsRusher'] ).reset_index(drop = True)
 return train
for df in [csv, test]:
df['stemmed'] = df['split'].apply(lambda x: [stemmer.stem(y)for y in x] )<feature_engineering>
def create_features(df, deploy=False):
def new_X(x_coordinate, play_direction):
if play_direction == 'left':
return 120.0 - x_coordinate
else:
return x_coordinate
def new_line(rush_team, field_position, yardline):
if rush_team == field_position:
return 10.0 + yardline
else:
return 60.0 +(50 - yardline)
 def new_orientation(angle, play_direction):
if play_direction == 'left':
new_angle = 360.0 - angle
if new_angle == 360.0:
new_angle = 0.0
return new_angle
else:
return angle
def euclidean_distance(x1,y1,x2,y2):
x_diff =(x1-x2)**2
y_diff =(y1-y2)**2
return np.sqrt(x_diff + y_diff)
 def back_direction(orientation):
if orientation > 180.0:
return 1
else:
return 0
def update_yardline(df):
new_yardline = df[df['NflId'] == df['NflIdRusher']]
new_yardline['YardLine'] = new_yardline[['PossessionTeam','FieldPosition','YardLine']].apply(lambda x: new_line(x[0],x[1],x[2]), axis=1)
 new_yardline = new_yardline[['GameId','PlayId','YardLine']]
return new_yardline
def update_orientation(df, yardline):
df['X'] = df[['X','PlayDirection']].apply(lambda x: new_X(x[0],x[1]), axis=1)
 df['Orientation'] = df[['Orientation','PlayDirection']].apply(lambda x: new_orientation(x[0],x[1]), axis=1)
 df['Dir'] = df[['Dir','PlayDirection']].apply(lambda x: new_orientation(x[0],x[1]), axis=1)
 df = df.drop('YardLine', axis=1)
 df = pd.merge(df, yardline, on=['GameId','PlayId'], how='inner')
 return df
def back_features(df):
carriers = df[df['NflId'] == df['NflIdRusher']][['GameId','PlayId','NflIdRusher','X','Y','Orientation','Dir','YardLine']]
carriers['back_from_scrimmage'] = carriers['YardLine'] - carriers['X']
carriers['back_oriented_down_field'] = carriers['Orientation'].apply(lambda x: back_direction(x))
carriers['back_moving_down_field'] = carriers['Dir'].apply(lambda x: back_direction(x))
carriers = carriers.rename(columns={'X':'back_X',
'Y':'back_Y'})
 carriers = carriers[['GameId','PlayId','NflIdRusher','back_X','back_Y','back_from_scrimmage','back_oriented_down_field','back_moving_down_field']]
return carriers
def features_relative_to_back(df, carriers):
player_distance = df[['GameId','PlayId','NflId','X','Y']]
player_distance = pd.merge(player_distance, carriers, on=['GameId','PlayId'], how='inner')
 player_distance = player_distance[player_distance['NflId'] != player_distance['NflIdRusher']]
player_distance['dist_to_back'] = player_distance[['X','Y','back_X','back_Y']].apply(lambda x: euclidean_distance(x[0],x[1],x[2],x[3]), axis=1)
 player_distance = player_distance.groupby(['GameId','PlayId','back_from_scrimmage','back_oriented_down_field','back_moving_down_field'])\ 
.agg({'dist_to_back':['min','max','mean','std']})\ 
.reset_index()
player_distance.columns = ['GameId','PlayId','back_from_scrimmage','back_oriented_down_field','back_moving_down_field',
'min_dist','max_dist','mean_dist','std_dist']
return player_distance
def defense_features(df):
rusher = df[df['NflId'] == df['NflIdRusher']][['GameId','PlayId','Team','X','Y']]
rusher.columns = ['GameId','PlayId','RusherTeam','RusherX','RusherY']
defense = pd.merge(df,rusher,on=['GameId','PlayId'],how='inner')
 defense = defense[defense['Team'] != defense['RusherTeam']][['GameId','PlayId','X','Y','RusherX','RusherY']]
defense['def_dist_to_back'] = defense[['X','Y','RusherX','RusherY']].apply(lambda x: euclidean_distance(x[0],x[1],x[2],x[3]), axis=1)
 defense = defense.groupby(['GameId','PlayId'])\ 
.agg({'def_dist_to_back':['min','max','mean','std']})\ 
.reset_index()
defense.columns = ['GameId','PlayId','def_min_dist','def_max_dist','def_mean_dist','def_std_dist']
return defense
def rusher_features(df):
rusher = df[df['NflId'] == df['NflIdRusher']][['GameId','PlayId','Dir', 'S', 'A', 'X', 'Y']]
rusher.columns = ['GameId','PlayId', 'RusherDir', 'RusherS', 'RusherA', 'RusherX', 'RusherY']
radian_angle =(90 - rusher['RusherDir'])* np.pi / 180.0
v_horizontal = np.abs(rusher['RusherS'] * np.cos(radian_angle))
v_vertical = np.abs(rusher['RusherS'] * np.sin(radian_angle))
rusher['v_horizontal'] = v_horizontal
rusher['v_vertical'] = v_vertical
rusher.columns = ['GameId','PlayId', 'RusherDir', 'RusherS','RusherA','RusherX', 'RusherY','v_horizontal', 'v_vertical']
return rusher
def static_features(df):
add_new_feas = []
df['PlayerHeight_dense'] = df['PlayerHeight'].apply(lambda x: 12*int(x.split('-')[0])+int(x.split('-')[1]))
add_new_feas.append('PlayerHeight_dense')
 df['TimeHandoff'] = df['TimeHandoff'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
df['TimeSnap'] = df['TimeSnap'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
df['TimeDelta'] = df.apply(lambda row:(row['TimeHandoff'] - row['TimeSnap'] ).total_seconds() , axis=1)
 df['PlayerBirthDate'] =df['PlayerBirthDate'].apply(lambda x: datetime.datetime.strptime(x, "%m/%d/%Y"))
seconds_in_year = 60*60*24*365.25
df['PlayerAge'] = df.apply(lambda row:(row['TimeHandoff']-row['PlayerBirthDate'] ).total_seconds() /seconds_in_year, axis=1)
 add_new_feas.append('PlayerAge')
 df['WindSpeed_ob'] = df['WindSpeed'].apply(lambda x: x.lower().replace('mph', '' ).strip() if not pd.isna(x)else x)
 df['WindSpeed_ob'] = df['WindSpeed_ob'].apply(lambda x:(int(x.split('-')[0])+int(x.split('-')[1])) /2 if not pd.isna(x)and '-' in x else x)
 df['WindSpeed_ob'] = df['WindSpeed_ob'].apply(lambda x:(int(x.split() [0])+int(x.split() [-1])) /2 if not pd.isna(x)and type(x)!=float and 'gusts up to' in x else x)
 df['WindSpeed_dense'] = df['WindSpeed_ob'].apply(strtofloat)
 add_new_feas.append('WindSpeed_dense')
 df["Orientation_ob"] = df["Orientation"].apply(lambda x : orientation_to_cat(x)).astype("object")
 df["Dir_ob"] = df["Dir"].apply(lambda x : orientation_to_cat(x)).astype("object")
 df["Orientation_sin"] = df["Orientation"].apply(lambda x : np.sin(x/360 * 2 * np.pi))
df["Orientation_cos"] = df["Orientation"].apply(lambda x : np.cos(x/360 * 2 * np.pi))
df["Dir_sin"] = df["Dir"].apply(lambda x : np.sin(x/360 * 2 * np.pi))
df["Dir_cos"] = df["Dir"].apply(lambda x : np.cos(x/360 * 2 * np.pi))
add_new_feas.append("Dir_sin")
 add_new_feas.append("Dir_cos")
 df["diffScoreBeforePlay"] = df["HomeScoreBeforePlay"] - df["VisitorScoreBeforePlay"]
add_new_feas.append("diffScoreBeforePlay")
 static_features = df[df['NflId'] == df['NflIdRusher']][add_new_feas+['GameId','PlayId','X','Y','S','A','Dis','Orientation','Dir',
'YardLine','Quarter','Down','Distance','DefendersInTheBox']].drop_duplicates()
static_features.fillna(-999,inplace=True)
 return static_features
def combine_features(relative_to_back, defense,rushing, static, deploy=deploy):
df = pd.merge(relative_to_back,defense,on=['GameId','PlayId'],how='inner')
 df = pd.merge(df,rushing,on=['GameId','PlayId'],how='inner')
 df = pd.merge(df,static,on=['GameId','PlayId'],how='inner')
 if not deploy:
df = pd.merge(df, outcomes, on=['GameId','PlayId'], how='inner')
 return df
yardline = update_yardline(df)
 df = update_orientation(df, yardline)
 back_feats = back_features(df)
 rel_back = features_relative_to_back(df, back_feats)
 def_feats = defense_features(df)
 rush_feats = rusher_features(df)
 static_feats = static_features(df)
 basetable = combine_features(rel_back, def_feats,rush_feats,static_feats, deploy=deploy)
 return basetable
vc = pd.Series([y for x in csv.stemmed for y in x] ).value_counts()
words_to_remove = [w for w in vc.index if vc[w] <= 4]
print('This will reduce to {} words'.format(
 len(set(vc.index ).difference(words_to_remove)) , len(tags)))
 unique_other_words = sorted(list(set(
 [word for sentence in test.split for word in sentence] ).union(
 [word for sentence in test.split for word in sentence] ).difference(
 unique_words)))
 word_removal_dict = {w: '' for w in {y for x in test.stemmed for y in x}}
word_removal_dict.update({w: w for w in vc.index})
 word_removal_dict.update({w: '' for w in words_to_remove})
 word_removal_dict[''] = ''
good_words = set(vc.index ).difference(words_to_remove)
 for df in [csv, test]:
df['reduced'] = df['stemmed'].apply(lambda x: [word_removal_dict[y] for y in x])
 for df in [csv, test]:
df['reduced2'] = [[y if y in good_words else df.loc[i,'PosTag'][j] for j,y in enumerate(df.loc[i,'stemmed'])] for i in df.index];<feature_engineering>
%time train_basetable = create_features(train, False )
def group(x, l):
return ['_'.join(x[i:i+l])for i in range(len(x)-l+1)]
twin_names = ['pairs', 'triplets', 'quadruplets', 'quintuplets',
'sextuplets', 'septuplets', 'octuplets', 'nonuplets']
for i,name in enumerate(twin_names):
l = i+2
print(l)
 for df in [csv, test]:
df[name] = df['reduced2'].apply(group, args=(l,))<count_values>
X = train_basetable.copy()
yards = X.Yards
y = np.zeros(( yards.shape[0], 199))
for idx, target in enumerate(list(yards)) :
y[idx][99 + target] = 1
X.drop(['GameId','PlayId','Yards'], axis=1, inplace=True )
for name in twin_names:
vc = pd.Series([y for x in csv[name] for y in set(x)] ).value_counts()
print('There are {} {}, {} appearing more than once, {} appearing more than twice, {} appearing more than 4 times'.format(
 len(vc), name, len(vc[vc>1]), len(vc[vc>2]), len(vc[vc>4])) )<data_type_conversions>
scaler = StandardScaler()
X = scaler.fit_transform(X )
plt.style.use('ggplot')
 plt.rcParams['font.size'] = 16
for i,name in enumerate(twin_names):
l = i+2
twin_count = {'ALL': pd.Series([y for x in csv[name] for y in set(x)] ).value_counts() }
for auth in authors:
twin_count[auth] = pd.Series([y for x in csv.loc[csv.author==auth, name]
for y in x] ).value_counts()
twin_count = pd.DataFrame(twin_count ).fillna(0 ).astype(int ).sort_values('ALL', ascending=False)[['ALL']+authors]
plt.figure(figsize=(20,10))
bottom = np.zeros(( 20))
ind = np.arange(20)
 df = twin_count.head(20)
 for auth in authors:
vals = df[auth]
plt.bar(ind, vals, bottom=bottom, label = auth)
 bottom += vals
plt.plot(ind, df['ALL'] * twin_count[authors[0]].sum() / twin_count['ALL'].sum() , 'k--',
label='Expected cutoffs for
uninformative words')
 plt.plot(ind, df['ALL'] * twin_count[authors[:2]].values.sum() / twin_count['ALL'].sum() , 'k--', label='')
 plt.xticks(ind, df.index, rotation='vertical')
 plt.legend(fontsize=24)
 plt.title('Top 20 {} count split by author(dotted lines is the global average)'.format(name), fontsize=24)
 plt.xlim([-0.7,19.7])
 plt.show()<feature_engineering>
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.15, random_state=12345 )
dict_tag = {x: i for i,x in enumerate(tags_exp.keys())}
for df in [csv, test]:
df['PosTagNum'] = df['PosTag'].apply(lambda x: [dict_tag[y] for y in x])
 df['JoinTagNum'] = df['PosTagNum'].apply(lambda x: ' '.join([str(y)for y in x]))
csv['len'] = csv.split.apply(len ).apply(np.log)
 test['len'] = test.split.apply(len ).apply(np.log )<choose_model_class>
class CRPSCallback(Callback):
def __init__(self,validation, predict_batch_size=20, include_on_batch=False):
super(CRPSCallback, self ).__init__()
self.validation = validation
self.predict_batch_size = predict_batch_size
self.include_on_batch = include_on_batch
print('validation shape',len(self.validation))
def on_batch_begin(self, batch, logs={}):
pass
def on_train_begin(self, logs={}):
if not('CRPS_score_val' in self.params['metrics']):
self.params['metrics'].append('CRPS_score_val')
 def on_batch_end(self, batch, logs={}):
if(self.include_on_batch):
logs['CRPS_score_val'] = float('-inf')
 def on_epoch_end(self, epoch, logs={}):
logs['CRPS_score_val'] = float('-inf')
 if(self.validation):
X_valid, y_valid = self.validation[0], self.validation[1]
y_pred = self.model.predict(X_valid)
 y_true = np.clip(np.cumsum(y_valid, axis=1), 0, 1)
 y_pred = np.clip(np.cumsum(y_pred, axis=1), 0, 1)
 val_s =(( y_true - y_pred)** 2 ).sum(axis=1 ).sum(axis=0)/(199 * X_valid.shape[0])
 val_s = np.round(val_s, 6)
 logs['CRPS_score_val'] = val_s
def test_with_grammar(vectorizer=TfidfVectorizer(token_pattern=r'\w{1,}', sublinear_tf=True, ngram_range=(1,2)) ,
C_logit = [0.3, 1, 3, 10, 30], alpha_SGD = [1e-5, 3e-5, 1e-4, 3e-4, 1e-3],
alpha_NB = [0.01, 0.03, 0.1, 0.3, 1]):
this_range = trange(10)
 model_names = []
params = []
targets = []
preds = []
preds_calib_sig = []
preds_calib_iso = []
models = [LogisticRegression(C=c)for c in C_logit] + [
SGDClassifier(loss='modified_huber', alpha=a, max_iter=10000, tol=1e-4)for a in alpha_SGD] + [
MultinomialNB(alpha=a)for a in alpha_NB] + [
BernoulliNB(alpha=a)for a in alpha_NB]
for test_loop in this_range:
test = csv.iloc[int(len(csv)*test_loop/10): int(len(csv)*(test_loop+1)/10)]
train = csv.loc[list(set(csv.index ).difference(test.index)) ]
y_train = train.author.apply(lambda auth: authors_dict[auth] ).values
y_test = test.author.apply(lambda auth: authors_dict[auth] ).values
X_train = vectorizer.fit_transform(train.text.values)
 X_test = vectorizer.transform(test.text.values)
 grammar_train = vectorizer.fit_transform(train.JoinTagNum.values)
 grammar_test = vectorizer.transform(test.JoinTagNum.values)
 X_train = hstack([X_train, grammar_train, train.len.values.reshape(-1,1)])
 X_test = hstack([X_test, grammar_test, test.len.values.reshape(-1,1)])
 for m in models:
name = str(m ).split('(')[0]
if name.endswith('NB')or name == 'SGDClassifier':
param = m.alpha
elif name == 'SVC' or name == 'LogisticRegression':
param = m.C
this_range.set_postfix(working_on=name, step='base')
 m.fit(X_train, y_train)
 targets.append(y_test)
 model_names.append([name] * len(y_test))
params.append([param] * len(y_test))
preds.append(m.predict_proba(X_test))
this_range.set_postfix(working_on=name, step='sigmoid')
 m_sigmoid = CalibratedClassifierCV(m, method='sigmoid')
 m_sigmoid.fit(X_train, y_train)
 preds_calib_sig.append(m_sigmoid.predict_proba(X_test))
this_range.set_postfix(working_on=name, step='isotonic')
 m_isotonic = CalibratedClassifierCV(m, method='isotonic')
 m_isotonic.fit(X_train, y_train)
 preds_calib_iso.append(m_isotonic.predict_proba(X_test))
targets = np.concatenate(targets)
 preds = np.concatenate(preds)
 preds_calib_sig = np.concatenate(preds_calib_sig)
 preds_calib_iso = np.concatenate(preds_calib_iso)
 params = np.log10(np.concatenate(params))
model_names = np.concatenate(model_names)
 log_losses = -np.log(np.clip(preds[np.arange(len(preds)) , targets], 1e-15, 1-1e-15))
log_losses_sig = -np.log(np.clip(preds_calib_sig[np.arange(len(preds_calib_sig)) , targets], 1e-15, 1-1e-15))
log_losses_iso = -np.log(np.clip(preds_calib_iso[np.arange(len(preds_calib_iso)) , targets], 1e-15, 1-1e-15))
final_results = pd.DataFrame({'LogLoss': log_losses, 'Param': params, 'Names': model_names,
'Target': targets, 'Prediction': np.argmax(preds, axis=1),
'LogLoss Sigmoid': log_losses_sig, 'LogLoss Isotonic': log_losses_iso})
 final_results['Accuracy'] = final_results['Target'] == final_results['Prediction']
return pd.concat(( final_results[[c, 'Names', 'Param']].groupby(['Names', 'Param'] ).mean()
for c in('LogLoss', 'LogLoss Sigmoid', 'LogLoss Isotonic', 'Accuracy')) ,
axis=1 ).reset_index()<define_search_space>
def get_model(x_tr,y_tr,x_val,y_val):
inp = Input(shape =(x_tr.shape[1],))
x = Dense(1024, input_dim=X.shape[1], activation='relu' )(inp)
 x = Dropout(0.5 )(x)
 x = BatchNormalization()(x)
 x = Dense(512, activation='relu' )(x)
 x = Dropout(0.5 )(x)
 x = BatchNormalization()(x)
 x = Dense(256, activation='relu' )(x)
 x = Dropout(0.5 )(x)
 x = BatchNormalization()(x)
 out = Dense(199, activation='softmax' )(x)
 model = Model(inp,out)
 model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=[])
 es = EarlyStopping(monitor='CRPS_score_val',
mode='min',
restore_best_weights=True,
verbose=1,
patience=10)
 mc = ModelCheckpoint('best_model.h5',monitor='CRPS_score_val',mode='min',
save_best_only=True, verbose=1, save_weights_only=True)
 bsz = 1024
steps = x_tr.shape[0]/bsz
model.fit(x_tr, y_tr,callbacks=[CRPSCallback(validation =(x_val,y_val)) ,es,mc], epochs=100, batch_size=bsz,verbose=1)
 model.load_weights("best_model.h5")
 y_pred = model.predict(x_val)
 y_valid = y_val
y_true = np.clip(np.cumsum(y_valid, axis=1), 0, 1)
 y_pred = np.clip(np.cumsum(y_pred, axis=1), 0, 1)
 val_s =(( y_true - y_pred)** 2 ).sum(axis=1 ).sum(axis=0)/(199 * x_val.shape[0])
 crps = np.round(val_s, 6)
 return model,crps
with_grammar = pd.DataFrame([['BernoulliNB', -3.0, 1.6471344235434087, 0.4435087577077471, 0.3577320896648269, 0.8567853312222279], ['BernoulliNB', -2.5228787452803374, 1.4710867854088956, 0.43929662596014907, 0.3543656366534263, 0.859441238061188], ['BernoulliNB', -2.0, 1.2902726232856094, 0.4369954213267632, 0.3525028669614839, 0.8606159660861127], ['BernoulliNB', -1.5228787452803376, 1.1501147846426674, 0.44044722351873644, 0.3559070371653456, 0.8597987639818172], ['BernoulliNB', -1.0, 1.059813417422428, 0.4611156884810041, 0.3675970332149561, 0.8557638285918586], ['LogisticRegression', 1.0, 0.41495735633115627, 0.4444363365240902, 0.4519791696222668, 0.8443740742632412], ['LogisticRegression', 1.4771212547196624, 0.3967254346672535, 0.4279426091513384, 0.43648381860509605, 0.850196639256346], ['LogisticRegression', 2.0, 0.4030843012131652, 0.41870106490803444, 0.42726604153139947, 0.8536186730680831], ['MultinomialNB', -3.0, 0.43307769203579094, 0.3996930781027156, 0.3665698887670437, 0.8550998518821186], ['MultinomialNB', -2.5228787452803374, 0.3890398733992301, 0.3871984611130643, 0.3619716036094982, 0.859339087798151], ['MultinomialNB', -2.0, 0.3545547603091124, 0.37540682385085566, 0.3560837402829932, 0.8625568210838143], ['MultinomialNB', -1.5228787452803376, 0.34351097136696496, 0.3723802076864194, 0.3610605741745939, 0.8634250983196282], ['MultinomialNB', -1.0, 0.3740066997854423, 0.3944609074299107, 0.3932247328330751, 0.8538740487256755], ['SGDClassifier', -4.522878745280337, 2.834158930282594, 0.4398856555186023, 0.44728487427768865, 0.8379386076919149], ['SGDClassifier', -4.0, 1.1306407647492276, 0.4348249833675688, 0.44502743957344704, 0.8303794882271822], ['SGDClassifier', -3.5228787452803374, 0.7603235276871617, 0.4656250015696377, 0.4707740721717643, 0.8110730885132029]], columns=['Names', 'Param', 'LogLoss', 'LogLoss Sigmoid', 'LogLoss Isotonic', 'Accuracy'])
 plot_calibrated_results(with_grammar )<choose_model_class>
losses = []
models = []
crps_csv = []
s_time = time.time()
for k in range(2):
kfold = KFold(5, random_state = 42 + k, shuffle = True)
 for k_fold,(tr_inds, val_inds)in enumerate(kfold.split(yards)) :
print("-----------")
 print("-----------")
 tr_x,tr_y = X[tr_inds],y[tr_inds]
val_x,val_y = X[val_inds],y[val_inds]
model,crps = get_model(tr_x,tr_y,val_x,val_y)
 models.append(model)
 print("the %d fold crps is %f"%(( k_fold+1),crps))
crps_csv.append(crps)
 print("mean crps is %f"%np.mean(crps_csv))
def predict(x_te):
model_num = len(models)
 for k,m in enumerate(models):
if k==0:
y_pred = m.predict(x_te,batch_size=1024)
 else:
y_pred+=m.predict(x_te,batch_size=1024)
 y_pred = y_pred / model_num
return y_pred
previous_best = [('MultiNB', MultinomialNB(alpha=0.03)) , 
('Calibrated MultiNB', CalibratedClassifierCV(MultinomialNB(alpha=0.01), method='isotonic')) , 
('Calibrated BernoulliNB', CalibratedClassifierCV(BernoulliNB(alpha=0.01), method='isotonic')) , 
('Calibrated Huber', CalibratedClassifierCV(
 SGDClassifier(loss='modified_huber', alpha=1e-4, max_iter=10000, tol=1e-4), method='sigmoid')) , 
('Logit', LogisticRegression(C=30)) ]<prepare_x_and_y>
print("mean crps is %f"%np.mean(crps_csv))
<import_modules><EOS> 
%%time
if TRAIN_OFFLINE==False:
env = nflrush.make_env()
iter_test = env.iter_test()
for(test_df, sample_prediction_df)in iter_test:
basetable = create_features(test_df, deploy=True)
 basetable.drop(['GameId','PlayId'], axis=1, inplace=True)
 scaled_basetable = scaler.transform(basetable)
 y_pred = predict(scaled_basetable)
 y_pred = np.clip(np.cumsum(y_pred, axis=1), 0, 1 ).tolist() [0]
preds_df = pd.DataFrame(data=[y_pred], columns=sample_prediction_df.columns)
 env.predict(preds_df)
 env.write_submission_file()