From 4d2b37e6a33ef45231232720281bdf2faad259e4 Mon Sep 17 00:00:00 2001 From: mehak-sachdeva Date: Wed, 7 Dec 2016 15:21:00 -0500 Subject: [PATCH] pep-8 changes and model accuracy fucntion parameter changes --- .../crankshaft/segmentation/segmentation.py | 127 ++++++++++++------ 1 file changed, 84 insertions(+), 43 deletions(-) diff --git a/src/py/crankshaft/crankshaft/segmentation/segmentation.py b/src/py/crankshaft/crankshaft/segmentation/segmentation.py index ed61139..23c0afa 100644 --- a/src/py/crankshaft/crankshaft/segmentation/segmentation.py +++ b/src/py/crankshaft/crankshaft/segmentation/segmentation.py @@ -10,7 +10,8 @@ from sklearn import metrics from sklearn.cross_validation import train_test_split # Lower level functions -#---------------------- +# --------------------- + def replace_nan_with_mean(array): """ @@ -28,6 +29,7 @@ def replace_nan_with_mean(array): return array + def get_data(variable, feature_columns, query): """ Fetch data from the database, clean, and package into @@ -40,10 +42,15 @@ def get_data(variable, feature_columns, query): prepared data, packaged into NumPy arrays """ - columns = ','.join(['array_agg("{col}") As "{col}"'.format(col=col) for col in feature_columns]) + columns = ','.join(['array_agg("{col}") As "{col}"'.format(col=col) + for col in feature_columns]) try: - data = plpy.execute('''SELECT array_agg("{variable}") As target, {columns} FROM ({query}) As a'''.format( + data = plpy.execute(''' + SELECT + array_agg("{variable}") As target, + {columns} + FROM ({query}) As a'''.format( variable=variable, columns=columns, query=query)) @@ -54,34 +61,43 @@ def get_data(variable, feature_columns, query): target = np.array(data[0]['target']) # put n feature data arrays into an n x m array of arrays - features = np.column_stack([np.array(data[0][col], dtype=float) for col in feature_columns]) + features = np.column_stack([np.array(data[0][col], dtype=float) + for col in feature_columns]) return replace_nan_with_mean(target), replace_nan_with_mean(features) # High level interface # -------------------- -def create_and_predict_segment_agg(target, features, target_features, target_ids, model_parameters): + +def create_and_predict_segment_agg(target, features, target_features, + target_ids, model_parameters): """ - Version of create_and_predict_segment that works on arrays that come stright form the SQL calling - the function. + Version of create_and_predict_segment that works on arrays that come + straight form the SQL calling the function. Input: - @param target: The 1D array of lenth NSamples containing the target variable we want the model to predict - @param features: Thw 2D array of size NSamples * NFeatures that form the imput to the model - @param target_ids: A 1D array of target_ids that will be used to associate the results of the prediction with the rows which they come from - @param model_parameters: A dictionary containing parameters for the model. + @param target: The 1D array of lenth NSamples containing the target + variable we want the model to predict + @param features: The 2D array of size NSamples * NFeatures that + form the imput to the model + @param target_ids: A 1D array of target_ids that will be used to + associate the results of the prediction with the rows which + they come from + @param model_parameters: A dictionary containing parameters for the + model. """ clean_target = replace_nan_with_mean(target) clean_features = replace_nan_with_mean(features) target_features = replace_nan_with_mean(target_features) - model, accuracy = train_model(clean_target, clean_features, model_parameters, 0.2) + model, accuracy = train_model(clean_target, clean_features, + model_parameters, 0.2) prediction = model.predict(target_features) accuracy_array = [accuracy]*prediction.shape[0] - return zip(target_ids, prediction, np.full(prediction.shape, accuracy_array)) - + return zip(target_ids, prediction, + np.full(prediction.shape, accuracy_array)) def create_and_predict_segment(query, variable, target_query, model_params): @@ -90,15 +106,19 @@ def create_and_predict_segment(query, variable, target_query, model_params): Stuart Lynn """ - ## fetch column names + # fetch column names try: - columns = plpy.execute('SELECT * FROM ({query}) As a LIMIT 1 '.format(query=query))[0].keys() + columns = plpy.execute(''' + SELECT * + FROM ({query}) As a + LIMIT 1'''.format(query=query))[0].keys() except Exception, e: plpy.error('Failed to build segmentation model: %s' % e) - ## extract column names to be used in building the segmentation model - feature_columns = set(columns) - set([variable, 'cartodb_id', 'the_geom', 'the_geom_webmercator']) - ## get data from database + # extract column names to be used in building the segmentation model + feature_columns = set(columns) - set([variable, 'cartodb_id', + 'the_geom', 'the_geom_webmercator']) + # get data from database target, features = get_data(variable, feature_columns, query) model, accuracy = train_model(target, features, model_params, 0.2) @@ -109,49 +129,65 @@ def create_and_predict_segment(query, variable, target_query, model_params): def train_model(target, features, model_params, test_split): """ - Train the Gradient Boosting model on the provided data and calculate the accuracy of the model + Train the Gradient Boosting model on the provided data and calculate + the accuracy of the model Input: - @param target: 1D Array of the variable that the model is to be trianed to predict - @param features: 2D Array NSamples * NFeatures to use in trining the model - @param model_params: A dictionary of model parameters, the full specification can be found on the - scikit learn page for [GradientBoostingRegressor](http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingRegressor.html) - @parma test_split: The fraction of the data to be withheld for testing the model / calculating the accuray + @param target: 1D Array of the variable that the model is to be + trained to predict + @param features: 2D Array NSamples * NFeatures to use in trining + the model + @param model_params: A dictionary of model parameters, the full + specification can be found on the + scikit learn page for [GradientBoostingRegressor] + (http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingRegressor.html) + @parma test_split: The fraction of the data to be withheld for + testing the model / calculating the accuray """ - features_train, features_test, target_train, target_test = train_test_split(features, target, test_size=test_split) + features_train, features_test, target_train, target_test = + train_test_split(features, target, test_size=test_split) model = GradientBoostingRegressor(**model_params) model.fit(features_train, target_train) - accuracy = calculate_model_accuracy(model, features, target) + accuracy = calculate_model_accuracy(model, features_test, target_test) return model, accuracy -def calculate_model_accuracy(model, features, target): + +def calculate_model_accuracy(model, features_test, target_test): """ Calculate the mean squared error of the model prediction Input: @param model: model trained from input features - @param features: features to make a prediction from - @param target: target to compare prediction to + @param features_test: test features set to make a prediction from + @param target_target: test target set to compare predictions to Output: - mean squared error of the model prection compared to the target + mean squared error of the model prection compared to target_test """ - prediction = model.predict(features) - return metrics.mean_squared_error(prediction, target) + prediction = model.predict(features_test) + return metrics.mean_squared_error(prediction, target_test) -def predict_segment(model, features, target_query): + +def predict_segment(model, features_col, target_query): """ Use the provided model to predict the values for the new feature set Input: @param model: The pretrained model - @features: A list of features to use in the model prediction (list of column names) - @target_query: The query to run to obtain the data to predict on and the cartdb_ids associated with it. + @features_col: A list of features to use in the + model prediction (list of column names) + @target_query: The query to run to obtain the data to predict + on and the cartdb_ids associated with it. """ batch_size = 1000 - joined_features = ','.join(['"{0}"::numeric'.format(a) for a in features]) + joined_features = ','.join(['"{0}"::numeric'.format(a) + for a in features_col]) try: - cursor = plpy.cursor('SELECT Array[{joined_features}] As features FROM ({target_query}) As a'.format( - joined_features=joined_features, - target_query=target_query)) + cursor = plpy.cursor(''' + SELECT Array[{joined_features}] As features + FROM ({target_query}) As a''' + .format( + joined_features=joined_features, + target_query=target_query) + ) except Exception, e: plpy.error('Failed to build segmentation model: %s' % e) @@ -161,15 +197,20 @@ def predict_segment(model, features, target_query): rows = cursor.fetch(batch_size) if not rows: break - batch = np.row_stack([np.array(row['features'], dtype=float) for row in rows]) + batch = np.row_stack([np.array(row['features'], dtype=float) + for row in rows]) - #Need to fix this. Should be global mean. This will cause weird effects + # Need to fix this to global mean. This will cause weird effects batch = replace_nan_with_mean(batch) prediction = model.predict(batch) results.append(prediction) try: - cartodb_ids = plpy.execute('''SELECT array_agg(cartodb_id ORDER BY cartodb_id) As cartodb_ids FROM ({0}) As a'''.format(target_query))[0]['cartodb_ids'] + cartodb_ids = plpy.execute(''' + SELECT array_agg(cartodb_id + ORDER BY cartodb_id) As cartodb_ids + FROM ({0}) As a''' + .format(target_query))[0]['cartodb_ids'] except Exception, e: plpy.error('Failed to build segmentation model: %s' % e)