-
Notifications
You must be signed in to change notification settings - Fork 20
/
main.py
114 lines (97 loc) · 5.1 KB
/
main.py
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
106
107
108
109
110
111
112
113
114
"""
Code for generating an ensemble submission for the SeeClickFix contest hosted on Kaggle. It loads base
submission files generated by our team's (Bryan Gregory and Miroslaw Horbal) individual models then combines them
using segment based averaging.
Ensemble weights for each segment of data are stored in SETTINGS.json along with the filepaths for the base input
submission files. Note that base submission 0 corresponds to Bryan's model and base submission 1 is Miroslaw's model.
This relies on already generated submission files from the base models, so base models must be run prior to performing
the ensemble.
Requires: PANDAS >.13
NUMPY
"""
__author__ = ['Bryan Gregory','Miroslaw Horbal']
__email__ = ['[email protected]','[email protected]']
__date__ = '01-04-2013'
#Internal modules
import utils
#Start logger to record all info, warnings, and errors to Logs/logfile.log
log = utils.start_logging(__name__)
#External modules
import sys
import pandas as pd
import numpy as np
from datetime import datetime
def main():
#---Load environment settings from SETTINGS.json in root directory and build filepaths for all base submissions---#
settings = utils.load_settings('SETTINGS.json')
base_filepaths = (settings['file_bryan_submission'],
settings['file_miroslaw_submission'])
segment_weights = settings['ensemble_segment_weights']
segments = segment_weights.keys()
targets = segment_weights[segments[0]].keys()
#---Output the segment weights to be used for ensemble averaging of base submissions---#
log.info('==========ENSEMBLE WEIGHTS (B,M)============')
for segment in segment_weights:
log.info(segment.upper()+':')
for target in segment_weights[segment]:
log.info(' '+target.upper()+' -- ['+segment_weights[segment][target]['0']+','+
segment_weights[segment][target]['1']+']')
#---Load each base submission to a list of dataframes---#
base_subs = []
for file in base_filepaths:
try:
base_subs.append(pd.read_csv(file).set_index(['id'], drop=False).sort())
log.info('Base submission successfully loaded: %s.' % file)
except IOError:
log.info('Base submission file does not exist: %s. Run base model to generate, or update filepath.' %file)
sys.exit('---Exiting---')
utils.line_break()
#---Load id's labeled with segments to a dataframe used for segment based averaging---#
file = settings['file_segment_ids']
try:
segment_ids = pd.read_csv(file)
log.info('Segment IDs successfully loaded from: %s.' % file)
except IOError:
log.info('Segment IDs file does not exist: %s. Update filepath in SETTINGS.json.' % file)
utils.line_break()
#---Transform base predictions to log space prior to averaging, if selected in settings---#
if settings['avg_log_space'] == 'y':
log.info('Transforming base predictions to log space prior to averaging.')
for i in range(len(base_subs)):
for target in targets:
base_subs[i][target] = np.log(base_subs[i][target]+1)
utils.line_break()
#---Apply segment based weights to each base submission then combine them to create ensemble submission---#
log.info('Applying segment weights to base submissions then combining to create ensemble.')
for i in range(len(base_subs)):
#Merge the segment labels from the segment id's file with the base submission dataframe
base_subs[i] = base_subs[i].merge(segment_ids,on='id',how='inner')
for segment in segments:
for target in targets:
base_subs[i][target][base_subs[i]['Segment'] == segment] \
*= float(segment_weights[segment][target][str(i)])
del base_subs[i]['Segment']
ensemble_sub = base_subs[0].ix[:]
for i in range(len(base_subs)-1):
for target in targets:
ensemble_sub[target] += base_subs[i+1][target]
utils.line_break()
#---Transform ensemble predictions back to normal, if use log space averaging was selected in settings---#
if settings['avg_log_space'] == 'y':
log.info('Transforming ensemble predictions back to normal from log space.')
for target in targets:
ensemble_sub[target] = np.exp(ensemble_sub[target])-1
utils.line_break()
#---Apply any final target scalars to ensemble predictions---#
for target in targets:
ensemble_sub[target] *= float(settings['target_scalars'][target])
#---Output ensemble submission to directory set in SETTINGS.json, appending creation date and time---#
timestamp = datetime.now().strftime('%m-%d-%y_%H%M')
filename = settings['dir_ensemble_submissions']+'ensemble_predictions_'+timestamp+'.csv'
ensemble_sub.to_csv(filename, index=False)
log.info('Ensemble submission saved: %s' % filename)
utils.line_break()
#End main
log.info('Program executed successfully without error! Exiting.')
if __name__ == '__main__':
sys.exit(main())