From 51d65e775e129312753afa11fbc58fd114c5ce97 Mon Sep 17 00:00:00 2001 From: Nils Andre Treiber Date: Fri, 8 Nov 2013 17:00:01 +0100 Subject: [PATCH 01/24] New turbine for response curve --- .../{svr_response_curve.py => response_curve_quartett.py} | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename examples/prediction/{svr_response_curve.py => response_curve_quartett.py} (91%) diff --git a/examples/prediction/svr_response_curve.py b/examples/prediction/response_curve_quartett.py similarity index 91% rename from examples/prediction/svr_response_curve.py rename to examples/prediction/response_curve_quartett.py index afe405d..d39867c 100644 --- a/examples/prediction/svr_response_curve.py +++ b/examples/prediction/response_curve_quartett.py @@ -2,8 +2,10 @@ Response Curve of a Turbine -------------------------------------------------- -The response curve is the mapping from wind speed to wind power production. In -this example the response curve is learned via support vector regression. +The response curve illustrates the relationship between wind speed +and generated power. The response curve is fitted via k-nearest neighbor +regression. Distribution of wind speeds and frequencies of cut-out help +to interpret the response curve shape. """ # Author: Nils A. Treiber @@ -26,7 +28,7 @@ ds = NREL() -turbine = ds.get_turbine(NREL.park_id['palmsprings'], 2004, 2006) +turbine = ds.get_turbine(NREL.park_id['tehachapi'], 2004, 2006) timeseries = turbine.get_measurements() max_speed = 40 skip = 1 From d554b99ecc8712d48ace15e8d1c234688e9e0b5b Mon Sep 17 00:00:00 2001 From: Nils Andre Treiber Date: Fri, 8 Nov 2013 17:30:13 +0100 Subject: [PATCH 02/24] Response Curve without Output --- examples/prediction/response_curve_quartett.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/prediction/response_curve_quartett.py b/examples/prediction/response_curve_quartett.py index d39867c..9601448 100644 --- a/examples/prediction/response_curve_quartett.py +++ b/examples/prediction/response_curve_quartett.py @@ -47,7 +47,7 @@ # initialize KNN regressor from sklearn. k_neighbors = 30 -knn = KNeighborsRegressor(k_neighbors, 'uniform') +knn = KNeighborsRegressor(k_neighbors, 'uniform', warn_on_equidistant = False) # fitting the pattern-label pairs T = np.linspace(0, max_speed, 500)[:, np.newaxis] @@ -80,7 +80,6 @@ fraction[i] = np.float32(num_below_thres[i-start_speed])/(num_below_thres[i-start_speed]+num_over_thres[i-start_speed]) else: fraction[i] = -1 -print fraction From 3a5ef789ecae54c1745138cf04d86cace9326d8a Mon Sep 17 00:00:00 2001 From: Nils Andre Treiber Date: Fri, 8 Nov 2013 17:00:01 +0100 Subject: [PATCH 03/24] New turbine for response curve --- .../{svr_response_curve.py => response_curve_quartett.py} | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename examples/prediction/{svr_response_curve.py => response_curve_quartett.py} (91%) diff --git a/examples/prediction/svr_response_curve.py b/examples/prediction/response_curve_quartett.py similarity index 91% rename from examples/prediction/svr_response_curve.py rename to examples/prediction/response_curve_quartett.py index afe405d..d39867c 100644 --- a/examples/prediction/svr_response_curve.py +++ b/examples/prediction/response_curve_quartett.py @@ -2,8 +2,10 @@ Response Curve of a Turbine -------------------------------------------------- -The response curve is the mapping from wind speed to wind power production. In -this example the response curve is learned via support vector regression. +The response curve illustrates the relationship between wind speed +and generated power. The response curve is fitted via k-nearest neighbor +regression. Distribution of wind speeds and frequencies of cut-out help +to interpret the response curve shape. """ # Author: Nils A. Treiber @@ -26,7 +28,7 @@ ds = NREL() -turbine = ds.get_turbine(NREL.park_id['palmsprings'], 2004, 2006) +turbine = ds.get_turbine(NREL.park_id['tehachapi'], 2004, 2006) timeseries = turbine.get_measurements() max_speed = 40 skip = 1 From 20e707d7518cf805c2676a1e77137ea8e498981b Mon Sep 17 00:00:00 2001 From: Nils Andre Treiber Date: Fri, 8 Nov 2013 17:30:13 +0100 Subject: [PATCH 04/24] Response Curve without Output --- examples/prediction/response_curve_quartett.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/prediction/response_curve_quartett.py b/examples/prediction/response_curve_quartett.py index d39867c..9601448 100644 --- a/examples/prediction/response_curve_quartett.py +++ b/examples/prediction/response_curve_quartett.py @@ -47,7 +47,7 @@ # initialize KNN regressor from sklearn. k_neighbors = 30 -knn = KNeighborsRegressor(k_neighbors, 'uniform') +knn = KNeighborsRegressor(k_neighbors, 'uniform', warn_on_equidistant = False) # fitting the pattern-label pairs T = np.linspace(0, max_speed, 500)[:, np.newaxis] @@ -80,7 +80,6 @@ fraction[i] = np.float32(num_below_thres[i-start_speed])/(num_below_thres[i-start_speed]+num_over_thres[i-start_speed]) else: fraction[i] = -1 -print fraction From fa7b77601ea213509250e8158a7c5577fad39073 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Mon, 11 Nov 2013 15:34:34 +0100 Subject: [PATCH 05/24] added smoothing operator; added benchmark class; added benchmark example --- examples/preprocessing/smoothing.py | 32 +++++++ windml/benchmark/__init__.py | 0 windml/benchmark/benchmark.py | 127 +++++++++++++++++++++++++++ windml/benchmark/testbeds.py | 114 ++++++++++++++++++++++++ windml/prediction/__init__.py | 0 windml/prediction/smoothed_linreg.py | 72 +++++++++++++++ windml/prediction/std_linreg.py | 62 +++++++++++++ windml/preprocessing/smoother.py | 66 ++++++++++++++ windml/visualization/colorset.py | 1 + 9 files changed, 474 insertions(+) create mode 100644 examples/preprocessing/smoothing.py create mode 100644 windml/benchmark/__init__.py create mode 100644 windml/benchmark/benchmark.py create mode 100644 windml/benchmark/testbeds.py create mode 100644 windml/prediction/__init__.py create mode 100644 windml/prediction/smoothed_linreg.py create mode 100644 windml/prediction/std_linreg.py create mode 100644 windml/preprocessing/smoother.py create mode 100644 windml/visualization/colorset.py diff --git a/examples/preprocessing/smoothing.py b/examples/preprocessing/smoothing.py new file mode 100644 index 0000000..12e0918 --- /dev/null +++ b/examples/preprocessing/smoothing.py @@ -0,0 +1,32 @@ +""" +Smoothing of a Time Series +-------------------------------------------------- + +This example shows how to smooth a time series with the +smoothen preprocessing operator. +""" + +# Author: Nils A. Treiber +# Author: Jendrik Poloczek +# License: BSD 3 clause + +from matplotlib import dates +import matplotlib.pylab as plt +import numpy as np +import datetime, time + +from windml.datasets.nrel import NREL +from windml.visualization.plot_timeseries import plot_timeseries +from windml.preprocessing.preprocessing import smoothen + +ds = NREL() +turbine = ds.get_turbine(NREL.park_id['tehachapi'], 2004) +measurements = turbine.get_measurements() + +smoothed_measurements = smoothen(measurements, interval_length=11) +turbine.add_measurements(smoothed_measurements) + +plot_timeseries(turbine, 0, 288) + + + diff --git a/windml/benchmark/__init__.py b/windml/benchmark/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/windml/benchmark/benchmark.py b/windml/benchmark/benchmark.py new file mode 100644 index 0000000..2b45e1b --- /dev/null +++ b/windml/benchmark/benchmark.py @@ -0,0 +1,127 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from testbeds import NREL_4_parks, QuickNDirty +from numpy import arange +import matplotlib.pyplot as plt +from windml.visualization.colorset import colorset + +class Benchmark(): + + testbeds = {'NREL_4_parks' : NREL_4_parks, + 'QuickNDirty' : QuickNDirty} + results = {} + + def _mse(self, y_hat, y_test): + mse_y_hat = 0 + for i in range(0, len(y_hat)): + mse_y_hat += (y_hat[i] - y_test[i]) ** 2 + + return (1.0/len(y_hat)) * mse_y_hat + + def run(self, regressor, testbed_name, parallel=False): + parks = self.testbeds[testbed_name]() + + def run_park(job): + park, testbed = job + wp_train, wp_test = testbed + + regressor.fit(wp_train) + y_hat, y_test = regressor.predict(wp_test) + + statistics = {'mse': self._mse(y_hat, y_test)} + return {'park' : park, 'statistics' : statistics} + + jobs = [] + for k, v in parks.iteritems(): + jobs.append((k,v)) + + # parallel + if(parallel == True): + from playdoh import map as pmap + from multiprocessing import cpu_count + cpus = cpu_count() + self.results[regressor] = pmap(run_park, jobs, cpu = cpus) + else: + # sequential + self.results[regressor] = map(run_park, jobs) + + return self.results + + def print_results(self): + for regressor, rresults in self.results.iteritems(): + print "Results for regressor %s" % str(regressor) + for rresult in rresults: + park = rresult['park'] + statistics = rresult['statistics'] + print "%s MSE: %f" % (park, statistics['mse']) + + def visualize_mse_on_parks(self): + plt.title("MSE on parks") + plt.xlabel("Park") + plt.ylabel("MSE") + + index = arange(len(self.results[self.results.keys()[0]])) + bar_width = 0.1 + + current_bar = 0 + for regressor, rresults in self.results.iteritems(): + + park_names = [] + mses = [] + + for result in rresults: + park = result['park'] + park_names.append(park) + mse = result['statistics']['mse'] + mses.append(mse) + + rects1 = plt.bar(index + current_bar * bar_width, + mses, + bar_width, + color=colorset[current_bar], + label=str(regressor)) + + current_bar = current_bar + 1 + + plt.xlabel('Park') + plt.ylabel('MSE') + plt.title('MSE by Park') + + plt.xticks(index + (current_bar * bar_width) / 2.0,\ + park_names) + plt.legend() + + plt.tight_layout() + plt.show() + diff --git a/windml/benchmark/testbeds.py b/windml/benchmark/testbeds.py new file mode 100644 index 0000000..2488c1a --- /dev/null +++ b/windml/benchmark/testbeds.py @@ -0,0 +1,114 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +def NREL_4_parks(): + """ Four parks, with 5 km radius, 2 years, horizon and feature + window equals 30 minutes.""" + + from windml.datasets.nrel import NREL + from windml.preprocessing.preprocessing import repair_nrel + + parks = {'palmsprings' : 1175, + 'reno' : 11637, + 'casper' : 23167, + 'carway' : 30498} + + testbed = {} + + # return X,y tuples + for park in parks.keys(): + + # training data ---- + windpark_train = NREL().get_windpark_nearest(parks[park], 5, 2004) + target = windpark_train.get_target() + + # repair NREL data + turbines = windpark_train.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:39457])) + + # test data ---- + windpark_test = NREL().get_windpark_nearest(parks[park], 5, 2005) + target = windpark_test.get_target() + + # repair NREL data + turbines = windpark_test.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:39457])) + + testbed[park] = (windpark_train, windpark_test) + + return testbed + +def QuickNDirty(): + """ Four parks, with 5 km radius, 2 years, horizon and feature + window equals 30 minutes.""" + + from windml.datasets.nrel import NREL + from windml.preprocessing.preprocessing import repair_nrel + + parks = {'palmsprings' : 1175, + 'reno' : 11637} + + testbed = {} + + # return X,y tuples + for park in parks.keys(): + + # training data ---- + windpark_train = NREL().get_windpark_nearest(parks[park], 5, 2004) + target = windpark_train.get_target() + + # repair NREL data + turbines = windpark_train.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:3457])) + + # test data ---- + windpark_test = NREL().get_windpark_nearest(parks[park], 5, 2005) + target = windpark_test.get_target() + + # repair NREL data + turbines = windpark_test.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:3457])) + + testbed[park] = (windpark_train, windpark_test) + + return testbed + + diff --git a/windml/prediction/__init__.py b/windml/prediction/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/windml/prediction/smoothed_linreg.py b/windml/prediction/smoothed_linreg.py new file mode 100644 index 0000000..bd84970 --- /dev/null +++ b/windml/prediction/smoothed_linreg.py @@ -0,0 +1,72 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from sklearn import linear_model +from windml.mapping.power_mapping import PowerMapping +from windml.preprocessing.preprocessing import smoothen +from windml.visualization.colorset import colorset + +class SmoothedLinreg(): + """ Standard spatio-temporal model with smoothing preprocessing, + PowerMapping and linear regression. """ + + def __init__(self, smooth=3): + self.model = linear_model.LinearRegression() + self.feature_window = 3 + self.horizon = 3 + self.smooth = smooth + + def fit(self, wp_train): + target = wp_train.get_target() + + # smoothing of all time series + turbines = wp_train.get_turbines() + for turbine in turbines: + turbine.add_measurements(\ + smoothen(turbine.get_measurements(), interval_length=self.smooth)) + + mapping = PowerMapping() + X_train = mapping.get_features_park(wp_train, self.feature_window, self.horizon) + y_train = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + self.model.fit(X_train, y_train) + + def predict(self, wp_test): + target = wp_test.get_target() + mapping = PowerMapping() + X_test = mapping.get_features_park(wp_test, self.feature_window, self.horizon) + y_test = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + return self.model.predict(X_test), y_test + + diff --git a/windml/prediction/std_linreg.py b/windml/prediction/std_linreg.py new file mode 100644 index 0000000..a4a645f --- /dev/null +++ b/windml/prediction/std_linreg.py @@ -0,0 +1,62 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from sklearn import linear_model +from windml.mapping.power_mapping import PowerMapping + +class StdLinreg(): + """ Standard spatio-temporal model with PowerMapping and + linear regression. """ + + def __init__(self): + self.model = linear_model.LinearRegression() + self.feature_window = 3 + self.horizon = 3 + + def fit(self, wp_train): + target = wp_train.get_target() + mapping = PowerMapping() + X_train = mapping.get_features_park(wp_train, self.feature_window, self.horizon) + y_train = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + self.model.fit(X_train, y_train) + + def predict(self, wp_test): + target = wp_test.get_target() + mapping = PowerMapping() + X_test = mapping.get_features_park(wp_test, self.feature_window, self.horizon) + y_test = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + return self.model.predict(X_test), y_test + + diff --git a/windml/preprocessing/smoother.py b/windml/preprocessing/smoother.py new file mode 100644 index 0000000..8cb644a --- /dev/null +++ b/windml/preprocessing/smoother.py @@ -0,0 +1,66 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from numpy import zeros, int32, float32 + +class Smoother(object): + def smooth(self, timeseries, args): + ilen = args['interval_length'] + + new_amount = timeseries.shape[0] + smoothed_ts = zeros((new_amount,), dtype=[('date', int32),\ + ('corrected_score', float32),\ + ('speed', float32)]) + + if(ilen % 2 == 0 or ilen == 1): + raise Exception("interval length must be odd and not 1.") + + padding = int((ilen - 1) / 2.0) + + # copy data in the beginning and the end cannot be smoothed + # because of padding + for i in range(0, padding): + smoothed_ts[i] = timeseries[i] # copy old data + for i in range(len(timeseries) - padding, len(timeseries)): + smoothed_ts[i] = timeseries[i] # copy old data + + # smooth data + for i in range(padding, len(timeseries) - padding): + sp_mean = timeseries[(i - padding):(i + padding)]['speed'].mean() + cs_mean = timeseries[(i - padding):(i + padding)]['corrected_score'].mean() + + smoothed_ts[i] = timeseries[i] # copy old data + smoothed_ts[i]['corrected_score'] = cs_mean + smoothed_ts[i]['speed'] = sp_mean + + return smoothed_ts diff --git a/windml/visualization/colorset.py b/windml/visualization/colorset.py new file mode 100644 index 0000000..a81c489 --- /dev/null +++ b/windml/visualization/colorset.py @@ -0,0 +1 @@ +colorset = ["#6699cc","#c4d8eb","#cccccc","#69bb3e","#b8e1a5"] From 4aebbf4d61e2343a41560914d251fc835ce3a1e2 Mon Sep 17 00:00:00 2001 From: Nils Andre Treiber Date: Fri, 8 Nov 2013 17:00:01 +0100 Subject: [PATCH 06/24] New turbine for response curve --- .../{svr_response_curve.py => response_curve_quartett.py} | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename examples/prediction/{svr_response_curve.py => response_curve_quartett.py} (91%) diff --git a/examples/prediction/svr_response_curve.py b/examples/prediction/response_curve_quartett.py similarity index 91% rename from examples/prediction/svr_response_curve.py rename to examples/prediction/response_curve_quartett.py index afe405d..d39867c 100644 --- a/examples/prediction/svr_response_curve.py +++ b/examples/prediction/response_curve_quartett.py @@ -2,8 +2,10 @@ Response Curve of a Turbine -------------------------------------------------- -The response curve is the mapping from wind speed to wind power production. In -this example the response curve is learned via support vector regression. +The response curve illustrates the relationship between wind speed +and generated power. The response curve is fitted via k-nearest neighbor +regression. Distribution of wind speeds and frequencies of cut-out help +to interpret the response curve shape. """ # Author: Nils A. Treiber @@ -26,7 +28,7 @@ ds = NREL() -turbine = ds.get_turbine(NREL.park_id['palmsprings'], 2004, 2006) +turbine = ds.get_turbine(NREL.park_id['tehachapi'], 2004, 2006) timeseries = turbine.get_measurements() max_speed = 40 skip = 1 From b14027b76e59ddd5e741d94f6e5aa94555a8ae6e Mon Sep 17 00:00:00 2001 From: Nils Andre Treiber Date: Fri, 8 Nov 2013 17:30:13 +0100 Subject: [PATCH 07/24] Response Curve without Output --- examples/prediction/response_curve_quartett.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/prediction/response_curve_quartett.py b/examples/prediction/response_curve_quartett.py index d39867c..9601448 100644 --- a/examples/prediction/response_curve_quartett.py +++ b/examples/prediction/response_curve_quartett.py @@ -47,7 +47,7 @@ # initialize KNN regressor from sklearn. k_neighbors = 30 -knn = KNeighborsRegressor(k_neighbors, 'uniform') +knn = KNeighborsRegressor(k_neighbors, 'uniform', warn_on_equidistant = False) # fitting the pattern-label pairs T = np.linspace(0, max_speed, 500)[:, np.newaxis] @@ -80,7 +80,6 @@ fraction[i] = np.float32(num_below_thres[i-start_speed])/(num_below_thres[i-start_speed]+num_over_thres[i-start_speed]) else: fraction[i] = -1 -print fraction From 8b2bbe7b1a8351ba0131c90858e5f3b7c177af0b Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Mon, 11 Nov 2013 15:34:34 +0100 Subject: [PATCH 08/24] added smoothing operator; added benchmark class; added benchmark example --- examples/preprocessing/smoothing.py | 32 +++++++ windml/benchmark/__init__.py | 0 windml/benchmark/benchmark.py | 127 +++++++++++++++++++++++++++ windml/benchmark/testbeds.py | 114 ++++++++++++++++++++++++ windml/prediction/__init__.py | 0 windml/prediction/smoothed_linreg.py | 72 +++++++++++++++ windml/prediction/std_linreg.py | 62 +++++++++++++ windml/preprocessing/smoother.py | 66 ++++++++++++++ windml/visualization/colorset.py | 1 + 9 files changed, 474 insertions(+) create mode 100644 examples/preprocessing/smoothing.py create mode 100644 windml/benchmark/__init__.py create mode 100644 windml/benchmark/benchmark.py create mode 100644 windml/benchmark/testbeds.py create mode 100644 windml/prediction/__init__.py create mode 100644 windml/prediction/smoothed_linreg.py create mode 100644 windml/prediction/std_linreg.py create mode 100644 windml/preprocessing/smoother.py create mode 100644 windml/visualization/colorset.py diff --git a/examples/preprocessing/smoothing.py b/examples/preprocessing/smoothing.py new file mode 100644 index 0000000..12e0918 --- /dev/null +++ b/examples/preprocessing/smoothing.py @@ -0,0 +1,32 @@ +""" +Smoothing of a Time Series +-------------------------------------------------- + +This example shows how to smooth a time series with the +smoothen preprocessing operator. +""" + +# Author: Nils A. Treiber +# Author: Jendrik Poloczek +# License: BSD 3 clause + +from matplotlib import dates +import matplotlib.pylab as plt +import numpy as np +import datetime, time + +from windml.datasets.nrel import NREL +from windml.visualization.plot_timeseries import plot_timeseries +from windml.preprocessing.preprocessing import smoothen + +ds = NREL() +turbine = ds.get_turbine(NREL.park_id['tehachapi'], 2004) +measurements = turbine.get_measurements() + +smoothed_measurements = smoothen(measurements, interval_length=11) +turbine.add_measurements(smoothed_measurements) + +plot_timeseries(turbine, 0, 288) + + + diff --git a/windml/benchmark/__init__.py b/windml/benchmark/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/windml/benchmark/benchmark.py b/windml/benchmark/benchmark.py new file mode 100644 index 0000000..2b45e1b --- /dev/null +++ b/windml/benchmark/benchmark.py @@ -0,0 +1,127 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from testbeds import NREL_4_parks, QuickNDirty +from numpy import arange +import matplotlib.pyplot as plt +from windml.visualization.colorset import colorset + +class Benchmark(): + + testbeds = {'NREL_4_parks' : NREL_4_parks, + 'QuickNDirty' : QuickNDirty} + results = {} + + def _mse(self, y_hat, y_test): + mse_y_hat = 0 + for i in range(0, len(y_hat)): + mse_y_hat += (y_hat[i] - y_test[i]) ** 2 + + return (1.0/len(y_hat)) * mse_y_hat + + def run(self, regressor, testbed_name, parallel=False): + parks = self.testbeds[testbed_name]() + + def run_park(job): + park, testbed = job + wp_train, wp_test = testbed + + regressor.fit(wp_train) + y_hat, y_test = regressor.predict(wp_test) + + statistics = {'mse': self._mse(y_hat, y_test)} + return {'park' : park, 'statistics' : statistics} + + jobs = [] + for k, v in parks.iteritems(): + jobs.append((k,v)) + + # parallel + if(parallel == True): + from playdoh import map as pmap + from multiprocessing import cpu_count + cpus = cpu_count() + self.results[regressor] = pmap(run_park, jobs, cpu = cpus) + else: + # sequential + self.results[regressor] = map(run_park, jobs) + + return self.results + + def print_results(self): + for regressor, rresults in self.results.iteritems(): + print "Results for regressor %s" % str(regressor) + for rresult in rresults: + park = rresult['park'] + statistics = rresult['statistics'] + print "%s MSE: %f" % (park, statistics['mse']) + + def visualize_mse_on_parks(self): + plt.title("MSE on parks") + plt.xlabel("Park") + plt.ylabel("MSE") + + index = arange(len(self.results[self.results.keys()[0]])) + bar_width = 0.1 + + current_bar = 0 + for regressor, rresults in self.results.iteritems(): + + park_names = [] + mses = [] + + for result in rresults: + park = result['park'] + park_names.append(park) + mse = result['statistics']['mse'] + mses.append(mse) + + rects1 = plt.bar(index + current_bar * bar_width, + mses, + bar_width, + color=colorset[current_bar], + label=str(regressor)) + + current_bar = current_bar + 1 + + plt.xlabel('Park') + plt.ylabel('MSE') + plt.title('MSE by Park') + + plt.xticks(index + (current_bar * bar_width) / 2.0,\ + park_names) + plt.legend() + + plt.tight_layout() + plt.show() + diff --git a/windml/benchmark/testbeds.py b/windml/benchmark/testbeds.py new file mode 100644 index 0000000..2488c1a --- /dev/null +++ b/windml/benchmark/testbeds.py @@ -0,0 +1,114 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +def NREL_4_parks(): + """ Four parks, with 5 km radius, 2 years, horizon and feature + window equals 30 minutes.""" + + from windml.datasets.nrel import NREL + from windml.preprocessing.preprocessing import repair_nrel + + parks = {'palmsprings' : 1175, + 'reno' : 11637, + 'casper' : 23167, + 'carway' : 30498} + + testbed = {} + + # return X,y tuples + for park in parks.keys(): + + # training data ---- + windpark_train = NREL().get_windpark_nearest(parks[park], 5, 2004) + target = windpark_train.get_target() + + # repair NREL data + turbines = windpark_train.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:39457])) + + # test data ---- + windpark_test = NREL().get_windpark_nearest(parks[park], 5, 2005) + target = windpark_test.get_target() + + # repair NREL data + turbines = windpark_test.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:39457])) + + testbed[park] = (windpark_train, windpark_test) + + return testbed + +def QuickNDirty(): + """ Four parks, with 5 km radius, 2 years, horizon and feature + window equals 30 minutes.""" + + from windml.datasets.nrel import NREL + from windml.preprocessing.preprocessing import repair_nrel + + parks = {'palmsprings' : 1175, + 'reno' : 11637} + + testbed = {} + + # return X,y tuples + for park in parks.keys(): + + # training data ---- + windpark_train = NREL().get_windpark_nearest(parks[park], 5, 2004) + target = windpark_train.get_target() + + # repair NREL data + turbines = windpark_train.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:3457])) + + # test data ---- + windpark_test = NREL().get_windpark_nearest(parks[park], 5, 2005) + target = windpark_test.get_target() + + # repair NREL data + turbines = windpark_test.get_turbines() + for t in range(len(turbines)): + turbines[t].add_measurements(\ + repair_nrel(turbines[t].get_measurements()[:3457])) + + testbed[park] = (windpark_train, windpark_test) + + return testbed + + diff --git a/windml/prediction/__init__.py b/windml/prediction/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/windml/prediction/smoothed_linreg.py b/windml/prediction/smoothed_linreg.py new file mode 100644 index 0000000..bd84970 --- /dev/null +++ b/windml/prediction/smoothed_linreg.py @@ -0,0 +1,72 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from sklearn import linear_model +from windml.mapping.power_mapping import PowerMapping +from windml.preprocessing.preprocessing import smoothen +from windml.visualization.colorset import colorset + +class SmoothedLinreg(): + """ Standard spatio-temporal model with smoothing preprocessing, + PowerMapping and linear regression. """ + + def __init__(self, smooth=3): + self.model = linear_model.LinearRegression() + self.feature_window = 3 + self.horizon = 3 + self.smooth = smooth + + def fit(self, wp_train): + target = wp_train.get_target() + + # smoothing of all time series + turbines = wp_train.get_turbines() + for turbine in turbines: + turbine.add_measurements(\ + smoothen(turbine.get_measurements(), interval_length=self.smooth)) + + mapping = PowerMapping() + X_train = mapping.get_features_park(wp_train, self.feature_window, self.horizon) + y_train = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + self.model.fit(X_train, y_train) + + def predict(self, wp_test): + target = wp_test.get_target() + mapping = PowerMapping() + X_test = mapping.get_features_park(wp_test, self.feature_window, self.horizon) + y_test = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + return self.model.predict(X_test), y_test + + diff --git a/windml/prediction/std_linreg.py b/windml/prediction/std_linreg.py new file mode 100644 index 0000000..a4a645f --- /dev/null +++ b/windml/prediction/std_linreg.py @@ -0,0 +1,62 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from sklearn import linear_model +from windml.mapping.power_mapping import PowerMapping + +class StdLinreg(): + """ Standard spatio-temporal model with PowerMapping and + linear regression. """ + + def __init__(self): + self.model = linear_model.LinearRegression() + self.feature_window = 3 + self.horizon = 3 + + def fit(self, wp_train): + target = wp_train.get_target() + mapping = PowerMapping() + X_train = mapping.get_features_park(wp_train, self.feature_window, self.horizon) + y_train = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + self.model.fit(X_train, y_train) + + def predict(self, wp_test): + target = wp_test.get_target() + mapping = PowerMapping() + X_test = mapping.get_features_park(wp_test, self.feature_window, self.horizon) + y_test = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + return self.model.predict(X_test), y_test + + diff --git a/windml/preprocessing/smoother.py b/windml/preprocessing/smoother.py new file mode 100644 index 0000000..8cb644a --- /dev/null +++ b/windml/preprocessing/smoother.py @@ -0,0 +1,66 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from numpy import zeros, int32, float32 + +class Smoother(object): + def smooth(self, timeseries, args): + ilen = args['interval_length'] + + new_amount = timeseries.shape[0] + smoothed_ts = zeros((new_amount,), dtype=[('date', int32),\ + ('corrected_score', float32),\ + ('speed', float32)]) + + if(ilen % 2 == 0 or ilen == 1): + raise Exception("interval length must be odd and not 1.") + + padding = int((ilen - 1) / 2.0) + + # copy data in the beginning and the end cannot be smoothed + # because of padding + for i in range(0, padding): + smoothed_ts[i] = timeseries[i] # copy old data + for i in range(len(timeseries) - padding, len(timeseries)): + smoothed_ts[i] = timeseries[i] # copy old data + + # smooth data + for i in range(padding, len(timeseries) - padding): + sp_mean = timeseries[(i - padding):(i + padding)]['speed'].mean() + cs_mean = timeseries[(i - padding):(i + padding)]['corrected_score'].mean() + + smoothed_ts[i] = timeseries[i] # copy old data + smoothed_ts[i]['corrected_score'] = cs_mean + smoothed_ts[i]['speed'] = sp_mean + + return smoothed_ts diff --git a/windml/visualization/colorset.py b/windml/visualization/colorset.py new file mode 100644 index 0000000..a81c489 --- /dev/null +++ b/windml/visualization/colorset.py @@ -0,0 +1 @@ +colorset = ["#6699cc","#c4d8eb","#cccccc","#69bb3e","#b8e1a5"] From 83ec93ec986144aadc03db897223a8d394d5bf28 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Tue, 12 Nov 2013 10:22:35 +0100 Subject: [PATCH 09/24] added example for benchmark; modified label in benchmark; added operator in prepro. --- examples/benchmark/comparison.py | 9 +++++++++ windml/benchmark/benchmark.py | 4 ++-- windml/preprocessing/preprocessing.py | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 examples/benchmark/comparison.py diff --git a/examples/benchmark/comparison.py b/examples/benchmark/comparison.py new file mode 100644 index 0000000..835eeb8 --- /dev/null +++ b/examples/benchmark/comparison.py @@ -0,0 +1,9 @@ +from windml.benchmark.benchmark import Benchmark +from windml.prediction.std_linreg import StdLinreg +from windml.prediction.smoothed_linreg import SmoothedLinreg + +bench = Benchmark() +bench.run(SmoothedLinreg(smooth=3), 'QuickNDirty') +bench.run(StdLinreg(), 'QuickNDirty') +bench.visualize_mse_on_parks() + diff --git a/windml/benchmark/benchmark.py b/windml/benchmark/benchmark.py index 2b45e1b..4f4a528 100644 --- a/windml/benchmark/benchmark.py +++ b/windml/benchmark/benchmark.py @@ -92,7 +92,7 @@ def visualize_mse_on_parks(self): plt.ylabel("MSE") index = arange(len(self.results[self.results.keys()[0]])) - bar_width = 0.1 + bar_width = 0.3 current_bar = 0 for regressor, rresults in self.results.iteritems(): @@ -110,7 +110,7 @@ def visualize_mse_on_parks(self): mses, bar_width, color=colorset[current_bar], - label=str(regressor)) + label=regressor.__class__.__name__) current_bar = current_bar + 1 diff --git a/windml/preprocessing/preprocessing.py b/windml/preprocessing/preprocessing.py index 629b8a3..39e1de6 100644 --- a/windml/preprocessing/preprocessing.py +++ b/windml/preprocessing/preprocessing.py @@ -42,6 +42,10 @@ from windml.preprocessing.duplicate_remover import DuplicateRemover from windml.preprocessing.nrel_repair import NRELRepair from windml.preprocessing.mreg_interpolation import MRegInterpolation +from windml.preprocessing.smoother import Smoother + +def smoothen(timeseries, **args): + return Smoother().smooth(timeseries, args) def repair_nrel(timeseries): return NRELRepair().repair(timeseries) From 2ad731c2fbcbe50811f54aa32c9de9c8172d03d7 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Tue, 12 Nov 2013 10:27:04 +0100 Subject: [PATCH 10/24] added example folder benchmark to example builder --- doc/sphinxext/example_builder.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/sphinxext/example_builder.py b/doc/sphinxext/example_builder.py index aff0418..c512489 100644 --- a/doc/sphinxext/example_builder.py +++ b/doc/sphinxext/example_builder.py @@ -447,12 +447,14 @@ def figure_contents(self, path, filelist): def subdir_contents(self, path, subdirs): subdirs = [os.path.join(path, subdir) for subdir in subdirs] - headlines = {'missingdata' : 'Missing Data', + headlines = {'benchmark' : 'Benchmark', + 'missingdata' : 'Missing Data', 'prediction' : 'Prediction', 'visualization' : 'Visualization', 'statistics' : 'Statistics'} - order = ['prediction', 'visualization', 'missingdata', 'statistics'] + order = ['prediction', 'visualization', 'missingdata', 'statistics',\ + 'benchmark'] toctree = ("\n\n" ".. toctree::\n" @@ -472,7 +474,7 @@ def subdir_contents(self, path, subdirs): rel_html = os.path.relpath(self.html_filename(f), path) toctree += " ./%s\n\n" % os.path.splitext(rel_html)[0] - + contents += (" .. figure:: ./%s\n" " :target: ./%s\n" "\n" From 8ed62f6f6662bb9a70c78b5e1a819a4e8fe4af5f Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Tue, 12 Nov 2013 11:02:36 +0100 Subject: [PATCH 11/24] added example description --- examples/benchmark/comparison.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/examples/benchmark/comparison.py b/examples/benchmark/comparison.py index 835eeb8..1aa75ab 100644 --- a/examples/benchmark/comparison.py +++ b/examples/benchmark/comparison.py @@ -1,3 +1,17 @@ +""" +MSE Comparison of Predictors +------------------------------------------------------------------------- + +This example shows a comparison of different predictors: Standard +spatio-temporal predictor and standard spatio-temporal predictor with +a smooth training set. The testbed is QuickNDirty, which is only used +for the example page presentation. +""" + +# Author: Jendrik Poloczek +# Author: Nils A. Treiber +# License: BSD 3 clause + from windml.benchmark.benchmark import Benchmark from windml.prediction.std_linreg import StdLinreg from windml.prediction.smoothed_linreg import SmoothedLinreg From 3d0d65ab2d502f1fcf961d3bee5d6cca828bf665 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Tue, 12 Nov 2013 11:14:43 +0100 Subject: [PATCH 12/24] modified example added predictor --- examples/benchmark/comparison.py | 9 ++-- windml/prediction/univariate_linreg.py | 68 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 windml/prediction/univariate_linreg.py diff --git a/examples/benchmark/comparison.py b/examples/benchmark/comparison.py index 1aa75ab..b500b1c 100644 --- a/examples/benchmark/comparison.py +++ b/examples/benchmark/comparison.py @@ -4,7 +4,7 @@ This example shows a comparison of different predictors: Standard spatio-temporal predictor and standard spatio-temporal predictor with -a smooth training set. The testbed is QuickNDirty, which is only used +a smooth training set. The testbed is NREL_4_parks, which is only used for the example page presentation. """ @@ -15,9 +15,12 @@ from windml.benchmark.benchmark import Benchmark from windml.prediction.std_linreg import StdLinreg from windml.prediction.smoothed_linreg import SmoothedLinreg +from windml.prediction.univariate_linreg import UnivariateLinreg bench = Benchmark() -bench.run(SmoothedLinreg(smooth=3), 'QuickNDirty') -bench.run(StdLinreg(), 'QuickNDirty') +bench.run(SmoothedLinreg(smooth=3), 'NREL_4_parks', parallel=True) +bench.run(StdLinreg(), 'NREL_4_parks', parallel=True) +bench.run(UnivariateLinreg(), 'NREL_4_parks', parallel=True) + bench.visualize_mse_on_parks() diff --git a/windml/prediction/univariate_linreg.py b/windml/prediction/univariate_linreg.py new file mode 100644 index 0000000..3b3fa48 --- /dev/null +++ b/windml/prediction/univariate_linreg.py @@ -0,0 +1,68 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from sklearn import linear_model +from windml.mapping.power_mapping import PowerMapping + +class UnivariateLinreg(): + """ Univariate model with PowerMapping and linear regression. This model + only uses measurements of the target turbine for training """ + + def __init__(self): + self.model = linear_model.LinearRegression() + self.feature_window = 3 + self.horizon = 3 + + def fit(self, wp_train): + target = wp_train.get_target() + turbines = wp_train.get_turbines() + wp_train.turbines = [turbines[-1]] # only use target + + mapping = PowerMapping() + X_train = mapping.get_features_park(wp_train, self.feature_window, self.horizon) + y_train = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + self.model.fit(X_train, y_train) + + def predict(self, wp_test): + target = wp_test.get_target() + + turbines = wp_test.get_turbines() + wp_test.turbines = [turbines[-1]] # only use target + + mapping = PowerMapping() + X_test = mapping.get_features_park(wp_test, self.feature_window, self.horizon) + y_test = mapping.get_labels_turbine(target, self.feature_window, self.horizon) + + return self.model.predict(X_test), y_test + From 4a30dc7741bcf08b78bbc613fafb2bbf6327bd29 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Tue, 12 Nov 2013 12:01:09 +0100 Subject: [PATCH 13/24] updated example; added naive predictor --- examples/benchmark/comparison.py | 15 +++++---- windml/benchmark/testbeds.py | 5 ++- windml/prediction/naive.py | 55 ++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 windml/prediction/naive.py diff --git a/examples/benchmark/comparison.py b/examples/benchmark/comparison.py index b500b1c..281d9bc 100644 --- a/examples/benchmark/comparison.py +++ b/examples/benchmark/comparison.py @@ -3,9 +3,10 @@ ------------------------------------------------------------------------- This example shows a comparison of different predictors: Standard -spatio-temporal predictor and standard spatio-temporal predictor with -a smooth training set. The testbed is NREL_4_parks, which is only used -for the example page presentation. +spatio-temporal predictor with linear regression, univariate predictor +with linear regression (only based on target turbine measurements) and +the naive / persistance model. The testbed is QuickNDirty, +which is only used for the example page presentation. """ # Author: Jendrik Poloczek @@ -14,13 +15,13 @@ from windml.benchmark.benchmark import Benchmark from windml.prediction.std_linreg import StdLinreg -from windml.prediction.smoothed_linreg import SmoothedLinreg from windml.prediction.univariate_linreg import UnivariateLinreg +from windml.prediction.naive import Naive bench = Benchmark() -bench.run(SmoothedLinreg(smooth=3), 'NREL_4_parks', parallel=True) -bench.run(StdLinreg(), 'NREL_4_parks', parallel=True) -bench.run(UnivariateLinreg(), 'NREL_4_parks', parallel=True) +bench.run(StdLinreg(), 'QuickNDirty') +bench.run(UnivariateLinreg(), 'QuickNDirty') +bench.run(Naive(), 'QuickNDirty') bench.visualize_mse_on_parks() diff --git a/windml/benchmark/testbeds.py b/windml/benchmark/testbeds.py index 2488c1a..e9e5462 100644 --- a/windml/benchmark/testbeds.py +++ b/windml/benchmark/testbeds.py @@ -80,7 +80,10 @@ def QuickNDirty(): from windml.preprocessing.preprocessing import repair_nrel parks = {'palmsprings' : 1175, - 'reno' : 11637} + 'reno' : 11637, + 'casper' : 23167, + 'carway' : 30498} + testbed = {} diff --git a/windml/prediction/naive.py b/windml/prediction/naive.py new file mode 100644 index 0000000..b3f6fe5 --- /dev/null +++ b/windml/prediction/naive.py @@ -0,0 +1,55 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +class Naive(): + """ Naive model """ + + def __init__(self): + self.horizon = 3 + + def fit(self, wp_train): + return # nothing to fit here + + def predict(self, wp_test): + target = wp_test.get_target() + measurements = target.get_measurements() + + y_predict = [] + y_test = [] + for i in range(measurements.shape[0] - self.horizon): + y_predict.append(measurements[i]['corrected_score']) + y_test.append(measurements[i + self.horizon]['corrected_score']) + + return y_predict, y_test + + From f75ff0cb66d255e20baa76f99fff16f7f0bf91e5 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Wed, 13 Nov 2013 09:35:48 +0100 Subject: [PATCH 14/24] removed obsolete imports --- examples/prediction/svr_regression_turbine.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/prediction/svr_regression_turbine.py b/examples/prediction/svr_regression_turbine.py index 8360bab..2ab8bff 100644 --- a/examples/prediction/svr_regression_turbine.py +++ b/examples/prediction/svr_regression_turbine.py @@ -29,15 +29,11 @@ import math import matplotlib.pyplot as plt -from sklearn.grid_search import GridSearchCV -from sklearn.cross_validation import KFold from sklearn import __version__ as sklearn_version from sklearn.svm import SVR - from numpy import zeros, float32 from windml.datasets.nrel import NREL from windml.mapping.power_mapping import PowerMapping -from sklearn.neighbors import KNeighborsRegressor # get windpark and corresponding target. forecast is for the target turbine park_id = NREL.park_id['tehachapi'] From b9664a6e3515054a483e07960edc404882c59825 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Wed, 13 Nov 2013 09:36:11 +0100 Subject: [PATCH 15/24] removed unused import --- examples/prediction/lin_regression_turbine.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/prediction/lin_regression_turbine.py b/examples/prediction/lin_regression_turbine.py index db4a0ed..031b706 100644 --- a/examples/prediction/lin_regression_turbine.py +++ b/examples/prediction/lin_regression_turbine.py @@ -28,8 +28,6 @@ from numpy import zeros, float32 from windml.datasets.nrel import NREL from windml.mapping.power_mapping import PowerMapping - -from sklearn.grid_search import GridSearchCV from sklearn import linear_model # get windpark and corresponding target. forecast is for the target turbine From fe3fc0fb6caa03da6e4a7c99054379bba91f71d6 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Wed, 13 Nov 2013 09:41:14 +0100 Subject: [PATCH 16/24] respect PEP 8 --- examples/prediction/response_curve_quartett.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/examples/prediction/response_curve_quartett.py b/examples/prediction/response_curve_quartett.py index 9601448..6840662 100644 --- a/examples/prediction/response_curve_quartett.py +++ b/examples/prediction/response_curve_quartett.py @@ -26,19 +26,16 @@ from windml.datasets.nrel import NREL from windml.visualization.plot_response_curve import plot_response_curve - ds = NREL() turbine = ds.get_turbine(NREL.park_id['tehachapi'], 2004, 2006) timeseries = turbine.get_measurements() max_speed = 40 skip = 1 - # plot true values as blue points speed = [m[2] for m in timeseries[::skip]] score = [m[1] for m in timeseries[::skip]] - # Second Plot: KNN-Interpolation # Built patterns und labels X_train = speed[0:len(speed):1] @@ -53,7 +50,6 @@ T = np.linspace(0, max_speed, 500)[:, np.newaxis] Y_hat = knn.fit(X_train_array, Y_train).predict(T) - # Last Plot start_speed = 15 threshold = 25 @@ -73,16 +69,16 @@ num_over_thres[elem] += 1 elem += 1 - fraction = np.zeros(max_speed, dtype=np.float32) for i in range(start_speed, len(fraction)): - if (np.float32(num_below_thres[i-start_speed]+num_over_thres[i-start_speed]) > 0): - fraction[i] = np.float32(num_below_thres[i-start_speed])/(num_below_thres[i-start_speed]+num_over_thres[i-start_speed]) + if (np.float32(num_below_thres[i-start_speed]+\ + num_over_thres[i-start_speed]) > 0): + fraction[i] = np.float32(num_below_thres[i-start_speed])/\ + (num_below_thres[i-start_speed]+\ + num_over_thres[i-start_speed]) else: fraction[i] = -1 - - figure = plt.figure(figsize=(15, 10)) plot_abs = plt.subplot(2, 2, 1) plt.title("Measurements") @@ -119,5 +115,3 @@ plt.ylabel("Probabilty of Cut-Out Events (Thres = 15)") plt.show() - - From d7eef1b3bc3df4c1dad898568d6bdf7dc247b0ab Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Wed, 13 Nov 2013 12:52:00 +0100 Subject: [PATCH 17/24] added new example; plot of joined wind speed probabilities --- examples/statistics/windspeed_joined.py | 23 ++++++ .../plot_wind_interdependecies.py | 77 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 examples/statistics/windspeed_joined.py create mode 100644 windml/visualization/plot_wind_interdependecies.py diff --git a/examples/statistics/windspeed_joined.py b/examples/statistics/windspeed_joined.py new file mode 100644 index 0000000..077ed13 --- /dev/null +++ b/examples/statistics/windspeed_joined.py @@ -0,0 +1,23 @@ +""" +Joined Probability of Wind Speeds +------------------------------------------------------------------------- + +This example plots show the joined probability of wind speeds. +""" + +# Author: Jendrik Poloczek +# License: BSD 3 clause + +import numpy as np + +from windml.datasets.nrel import NREL +from windml.visualization.plot_wind_interdependecies import plot_joined + +ds = NREL() +windpark = ds.get_windpark(NREL.park_id['tehachapi'], 3, 2004) + +turbines = windpark.get_turbines() +turbine_a = turbines[0] +turbine_b = turbines[1] + +plot_joined(turbine_a, turbine_b) diff --git a/windml/visualization/plot_wind_interdependecies.py b/windml/visualization/plot_wind_interdependecies.py new file mode 100644 index 0000000..f4b29c5 --- /dev/null +++ b/windml/visualization/plot_wind_interdependecies.py @@ -0,0 +1,77 @@ +""" +Copyright (c) 2013, +Fabian Gieseke, Justin P. Heinermann, Oliver Kramer, Jendrik Poloczek, +Nils A. Treiber +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of the Computational Intelligence Group of the University + of Oldenburg nor the names of its contributors may be used to endorse or + promote products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" +from mpl_toolkits.mplot3d import axes3d +from matplotlib import cm +import matplotlib.pyplot as plt +import numpy as np +import time + +def plot_joined(turbine_a, turbine_b): + + speeds_a = turbine_a.get_measurements()['speed'] + speeds_b = turbine_b.get_measurements()['speed'] + + bins = (0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25) + X_a, Y_a = np.histogram(speeds_a, bins = bins, density = True) + X_b, Y_b = np.histogram(speeds_b, bins = bins, density = True) + + akv = {k: v for k, v in zip(Y_a, X_a)} + bkv = {k: v for k, v in zip(Y_b, X_b)} + + def join(x,y): + return akv[x] * bkv[y] + + def generate(X,Y): + Z = np.zeros(X.shape) + for i in range(X.shape[0]): + Z[i] = map(join, X[i], Y[i]) + return Z + + fig = plt.figure() + ax = fig.add_subplot(111, projection='3d') + + xs = range(0, 25, 2) + ys = range(0, 25, 2) + X, Y = np.meshgrid(xs, ys) + Z = generate(X, Y) + + plot = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, linewidth=0,\ + cmap=cm.coolwarm) + + ax.set_xlabel("Turbine 1") + ax.set_ylabel("Turbine 2") + ax.set_zlabel("Joined Windspeed Probability") + ax.set_title("Joined Windspeed Probability") + + plt.show() + From 2da00d63fb2bab48a6a9ce9dd836a6f6c6518f91 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Wed, 13 Nov 2013 16:11:02 +0100 Subject: [PATCH 18/24] added new example --- examples/statistics/prop_ramps.py | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 examples/statistics/prop_ramps.py diff --git a/examples/statistics/prop_ramps.py b/examples/statistics/prop_ramps.py new file mode 100644 index 0000000..922d7bc --- /dev/null +++ b/examples/statistics/prop_ramps.py @@ -0,0 +1,44 @@ +""" +Propagating Wind Changes +-------------------------------------------------- +""" + +# Author: Jendrik Poloczek +# Author: Oliver Kramer +# License: BSD 3 clause + +import matplotlib.pyplot as plt +import numpy as np +from windml.datasets.nrel import NREL + +ds = NREL() + +park_id = NREL.park_id['tehachapi'] +windpark = NREL().get_windpark(park_id, 3, 2004) +turbines = windpark.get_turbines() +t1, t2 = turbines[0], turbines[1] + +i=7 +window_size = 200 +steps = 3 + +X1 = t1.get_measurements()['speed'] +X2 = t2.get_measurements()['speed'] +X1 = X1[i*window_size:i*window_size+window_size] +X2 = X2[i*window_size:i*window_size+window_size] + +x1= [] +x2 = [] +colors = [] +for i in xrange(len(X1)-steps): + x1.append(X1[i]) + x2.append(X2[i+steps]) + # depending on the distance to the diagonal, + # choose the color of the event + colors.append(abs(X1[i]-X2[i+steps])) + ax = plt.subplot(1, 1, 1) +plt.title("Propagating Ramps, Horizon = "+str(steps)) +ax.scatter(x1, x2, s=15, c=colors, linewidth=0.0, cmap=plt.cm.jet) +plt.xlabel("Wind Speed in time t (Turbine 1)") +plt.ylabel("Wind Speed in time t + 3 (Turbine 2)") +plt.show() From 6729edeb1e3af8225259d3d43f33bd415160e50b Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Thu, 14 Nov 2013 10:49:52 +0100 Subject: [PATCH 19/24] added axis label for example --- examples/statistics/ramps.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/statistics/ramps.py b/examples/statistics/ramps.py index c4149d7..3118953 100644 --- a/examples/statistics/ramps.py +++ b/examples/statistics/ramps.py @@ -8,6 +8,7 @@ """ # Author: Oliver Kramer +# Author: Jendrik Poloczek # License: BSD 3 clause import matplotlib.pyplot as plt @@ -41,6 +42,9 @@ colors.append(abs(X[i]-X[i+steps])) ax = plt.subplot(2, 2, j) plt.title("Ramps, Horizon = "+str(steps)) + plt.xlabel("Wind Speed in time t") + plt.ylabel("Wind Speed in time t + " +str(steps)) + ax.scatter(x1, x2, s=15, c=colors, linewidth=0.0, cmap=plt.cm.jet) j+=1 From bd461de473871154830e792bd4d6636f54b522b5 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Thu, 14 Nov 2013 10:51:11 +0100 Subject: [PATCH 20/24] added uom --- examples/statistics/ramps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/statistics/ramps.py b/examples/statistics/ramps.py index 3118953..96fed84 100644 --- a/examples/statistics/ramps.py +++ b/examples/statistics/ramps.py @@ -42,8 +42,8 @@ colors.append(abs(X[i]-X[i+steps])) ax = plt.subplot(2, 2, j) plt.title("Ramps, Horizon = "+str(steps)) - plt.xlabel("Wind Speed in time t") - plt.ylabel("Wind Speed in time t + " +str(steps)) + plt.xlabel("Wind Speed [m/s] in time t") + plt.ylabel("Wind Speed [m/s] in time t + " +str(steps)) ax.scatter(x1, x2, s=15, c=colors, linewidth=0.0, cmap=plt.cm.jet) j+=1 From 4509a23fdee8683ad6f88c330e715c4d30c3a9d1 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Thu, 14 Nov 2013 11:45:08 +0100 Subject: [PATCH 21/24] added (better) axis label with uom --- examples/prediction/knn_regression_turbine.py | 26 +++++++++++-------- examples/prediction/lin_regression_turbine.py | 26 +++++++++++-------- examples/prediction/svr_regression_turbine.py | 26 +++++++++++-------- 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/examples/prediction/knn_regression_turbine.py b/examples/prediction/knn_regression_turbine.py index 4a5f777..f528fab 100644 --- a/examples/prediction/knn_regression_turbine.py +++ b/examples/prediction/knn_regression_turbine.py @@ -86,7 +86,7 @@ figure = plt.figure(figsize=(15, 10)) plot_abs = plt.subplot(2, 2, 1) -plt.title("Absolute Labels and True Measurements") +plt.title("Predicted and True Measurements") # Array of true labels for plotting. y = zeros(len(y_hat)) @@ -95,35 +95,39 @@ time = range(0, len(y_hat)) plt.plot(time, y, "g-", label="Measurement") -plt.plot(time, y_hat, "r-", label="KNN Label") -plt.plot(time, naive_hat, "b-", label="Naive Label") +plt.plot(time, y_hat, "r-", label="KNN-predicted") +plt.plot(time, naive_hat, "b-", label="Naive-predicted") +plt.xlabel("Time [600s]") +plt.ylabel("Power [MW]") plt.xlim([9600, 9750]) plt.ylim([-30, 50]) plt.legend() plot_scatter = plt.subplot(2, 2, 2) -plt.title("Naive Label and True Measurement") +plt.title("Naive-predicted and True Measurement") col = abs(y - naive_hat) plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) -plt.xlabel("Y") -plt.ylabel("Naive Label") +plt.xlabel("True Measurement [MW]") +plt.ylabel("Naive-predicted Measurement [MW]") plt.xlim([0, 30]) plt.ylim([0, 30]) plot_abs = plt.subplot(2, 2, 3) plt.title("Absolute Difference") -plt.plot(time, (y_hat - y), "r-", label="KNN Label") -plt.plot(time, (naive_hat - y), "b-", label="Naive Label") +plt.plot(time, (y_hat - y), "r-", label="KNN-predicted") +plt.plot(time, (naive_hat - y), "b-", label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-20, 30]) +plt.xlabel("Time [600s]") +plt.ylabel("Deviation of True Power [MW]") plt.legend() plot_scatter = plt.subplot(2, 2, 4) -plt.title("KNN Label and True Measurement") +plt.title("KNN-predicted and True Measurement") col = abs(y - y_hat) plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) -plt.xlabel("Y") -plt.ylabel("KNN Label") +plt.xlabel("True Measurement [MW]") +plt.ylabel("KNN-predicted Measurement [MW]") plt.xlim([0, 30]) plt.ylim([0, 30]) diff --git a/examples/prediction/lin_regression_turbine.py b/examples/prediction/lin_regression_turbine.py index 031b706..8526d81 100644 --- a/examples/prediction/lin_regression_turbine.py +++ b/examples/prediction/lin_regression_turbine.py @@ -80,7 +80,7 @@ figure = plt.figure(figsize=(15, 10)) plot_abs = plt.subplot(2, 2, 1) -plt.title("Absolute Labels and True Measurements") +plt.title("Predicted and True Measurements") # Array of true labels for plotting. y = zeros(len(y_hat)) @@ -89,35 +89,39 @@ time = range(0, len(y_hat)) plt.plot(time, y, "g-", label="Measurement") -plt.plot(time, y_hat, "r-", label="Linear Label") -plt.plot(time, naive_hat, "b-", label="Naive Label") +plt.plot(time, y_hat, "r-", label="Linear-predicted") +plt.plot(time, naive_hat, "b-", label="Naive-predicted") +plt.xlabel("Time [600s]") +plt.ylabel("Power [MW]") plt.xlim([9600, 9750]) plt.ylim([-30, 50]) plt.legend() plot_scatter = plt.subplot(2, 2, 2) -plt.title("Naive Label and True Measurement") +plt.title("Naive-predicted and True Measurement") col = abs(y - naive_hat) plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) -plt.xlabel("Y") -plt.ylabel("Naive Label") +plt.xlabel("True Measurement [MW]") +plt.ylabel("Naive-predicted Measurement [MW]") plt.xlim([0, 30]) plt.ylim([0, 30]) plot_abs = plt.subplot(2, 2, 3) plt.title("Absolute Difference") -plt.plot(time, (y_hat - y), "r-", label="Linear Label") -plt.plot(time, (naive_hat - y), "b-", label="Naive Label") +plt.plot(time, (y_hat - y), "r-", label="Linear-predicted") +plt.plot(time, (naive_hat - y), "b-", label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-20, 30]) +plt.xlabel("Time [600s]") +plt.ylabel("Deviation of True Power [MW]") plt.legend() plot_scatter = plt.subplot(2, 2, 4) -plt.title("Linear Label and True Measurement") +plt.title("Linear-predicted and True Measurement") col = abs(y - y_hat) plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) -plt.xlabel("Y") -plt.ylabel("Linear Label") +plt.xlabel("True Measurement [MW]") +plt.ylabel("Linear-predicted Measurement [MW]") plt.xlim([0, 30]) plt.ylim([0, 30]) diff --git a/examples/prediction/svr_regression_turbine.py b/examples/prediction/svr_regression_turbine.py index 2ab8bff..e4e0dea 100644 --- a/examples/prediction/svr_regression_turbine.py +++ b/examples/prediction/svr_regression_turbine.py @@ -114,7 +114,7 @@ figure = plt.figure(figsize=(15, 10)) plot_abs = plt.subplot(2, 2, 1) -plt.title("Absolute Labels and True Measurements") +plt.title("Predicted and True Measurements") # Array of true labels for plotting. y = zeros(len(y_hat)) @@ -123,35 +123,39 @@ time = range(0, len(y_hat)) plt.plot(time, y, "g-", label="Measurement") -plt.plot(time, y_hat, "r-", label="SVR Label") -plt.plot(time, naive_hat, "b-", label="Naive Label") +plt.plot(time, y_hat, "r-", label="SVR-predicted") +plt.plot(time, naive_hat, "b-", label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-30, 50]) +plt.xlabel("Time [600s]") +plt.ylabel("Power [MW]") plt.legend() plot_scatter = plt.subplot(2, 2, 2) -plt.title("Naive Label and True Measurement") +plt.title("Naive-predicted and True Measurement") col = abs(y - naive_hat) plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) -plt.xlabel("Y") -plt.ylabel("Naive Label") +plt.xlabel("True Measurement [MW]") +plt.ylabel("Naive-predicted Measurement [MW]") plt.xlim([0, 30]) plt.ylim([0, 30]) plot_abs = plt.subplot(2, 2, 3) plt.title("Absolute Difference") -plt.plot(time, (y_hat - y), "r-", label="SVR Label") -plt.plot(time, (naive_hat - y), "b-", label="Naive Label") +plt.plot(time, (y_hat - y), "r-", label="SVR-predicted") +plt.plot(time, (naive_hat - y), "b-", label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-20, 30]) +plt.xlabel("Time [600s]") +plt.ylabel("Deviation of True Power [MW]") plt.legend() plot_scatter = plt.subplot(2, 2, 4) -plt.title("SVR Label and True Measurement") +plt.title("SVR-predicted and True Measurement") col = abs(y - y_hat) plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) -plt.xlabel("Y") -plt.ylabel("SVR Label") +plt.xlabel("True Measurement [MW]") +plt.ylabel("SVR-predicted Measurement [MW]") plt.xlim([0, 30]) plt.ylim([0, 30]) # y_hat (SVR) might be greater than 30 and smaller than 0. From f105db853b910b6d25d31664e78b97a36614a769 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Thu, 14 Nov 2013 11:56:07 +0100 Subject: [PATCH 22/24] added (better) axis labels with uom --- examples/missingdata/mar_damaged.py | 2 +- examples/missingdata/mreg_knn_interpolation.py | 2 +- examples/missingdata/mreg_lin_interpolation.py | 2 +- examples/missingdata/mreg_svr_interpolation.py | 2 +- examples/missingdata/reconstruction.py | 4 ++-- examples/missingdata/reconstruction_prediction.py | 4 ++-- examples/prediction/compare_regressors_param.py | 2 +- examples/prediction/horizon_mse.py | 4 ++-- examples/statistics/windspeed_histogram.py | 6 +++++- windml/benchmark/benchmark.py | 8 ++------ windml/visualization/plot_multiple_timeseries.py | 4 ++-- windml/visualization/plot_timeseries.py | 2 +- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/examples/missingdata/mar_damaged.py b/examples/missingdata/mar_damaged.py index ba65c74..08c32c0 100644 --- a/examples/missingdata/mar_damaged.py +++ b/examples/missingdata/mar_damaged.py @@ -54,7 +54,7 @@ ax.grid(True) plt.ylim(-2, 32) -plt.ylabel("Corrected Power (MW), Wind Speed (m/s)") +plt.ylabel("Corrected Power [MW], Wind Speed [m/s]") plt.plot(d_time, y1, label = 'Power Production', color="b", alpha=0.5) plt.plot(d_time, y2, label = 'Wind Speed', color="g", alpha=0.5) diff --git a/examples/missingdata/mreg_knn_interpolation.py b/examples/missingdata/mreg_knn_interpolation.py index 690e023..bff2790 100644 --- a/examples/missingdata/mreg_knn_interpolation.py +++ b/examples/missingdata/mreg_knn_interpolation.py @@ -79,7 +79,7 @@ ax.grid(True) plt.ylim(-2, 32) -plt.ylabel("Corrected Power (MW), Wind Speed (m/s)") +plt.ylabel("Corrected Power [MW], Wind Speed [m/s]") plt.plot(d_time, y1, label = 'Power Production (interpolated)', color="b") plt.plot(d_time, y2, label = 'Wind Speed (interpolated)', color="g") diff --git a/examples/missingdata/mreg_lin_interpolation.py b/examples/missingdata/mreg_lin_interpolation.py index a95e4ce..d3e3c2f 100644 --- a/examples/missingdata/mreg_lin_interpolation.py +++ b/examples/missingdata/mreg_lin_interpolation.py @@ -78,7 +78,7 @@ ax.grid(True) plt.ylim(-2, 32) -plt.ylabel("Corrected Power (MW), Wind Speed (m/s)") +plt.ylabel("Corrected Power [MW], Wind Speed [m/s]") plt.plot(d_time, y1, label = 'Power Production (interpolated)', color="b") plt.plot(d_time, y2, label = 'Wind Speed (interpolated)', color="g") diff --git a/examples/missingdata/mreg_svr_interpolation.py b/examples/missingdata/mreg_svr_interpolation.py index ea53eb6..9c255cd 100644 --- a/examples/missingdata/mreg_svr_interpolation.py +++ b/examples/missingdata/mreg_svr_interpolation.py @@ -92,7 +92,7 @@ ax.grid(True) plt.ylim(-2, 32) -plt.ylabel("Corrected Power (MW), Wind Speed (m/s)") +plt.ylabel("Corrected Power [MW], Wind Speed [m/s]") plt.plot(d_time, y1, label = 'Power Production (interpolated)', color="b") plt.plot(d_time, y2, label = 'Wind Speed (interpolated)', color="g") diff --git a/examples/missingdata/reconstruction.py b/examples/missingdata/reconstruction.py index 31a841b..951571d 100644 --- a/examples/missingdata/reconstruction.py +++ b/examples/missingdata/reconstruction.py @@ -239,8 +239,8 @@ def to_percent(y, position): formatter = FuncFormatter(to_percent) plt.gca().xaxis.set_major_formatter(formatter) -plt.xlabel("Rate of Missing Data") -plt.ylabel("Reconstruction MSE") +plt.xlabel("Rate of Missing Data in Percent") +plt.ylabel("Reconstruction MSE of Power [MW]") plt.xlim([0.1, 0.9]) plt.ylim([0, 10]) plt.legend(loc="upper left") diff --git a/examples/missingdata/reconstruction_prediction.py b/examples/missingdata/reconstruction_prediction.py index 467a992..7ee01dc 100644 --- a/examples/missingdata/reconstruction_prediction.py +++ b/examples/missingdata/reconstruction_prediction.py @@ -251,8 +251,8 @@ def to_percent(y, position): formatter = FuncFormatter(to_percent) plt.gca().xaxis.set_major_formatter(formatter) -plt.xlabel("Rate of Missing Data") -plt.ylabel("Prediction MSE") +plt.xlabel("Rate of Missing Data in Percent") +plt.ylabel("Prediction MSE of Power [MW]") plt.xlim([0.1, 0.9]) plt.ylim([12.5, 16]) plt.legend(loc="upper left") diff --git a/examples/prediction/compare_regressors_param.py b/examples/prediction/compare_regressors_param.py index 810ce8a..169220d 100644 --- a/examples/prediction/compare_regressors_param.py +++ b/examples/prediction/compare_regressors_param.py @@ -95,7 +95,7 @@ def compute_mse(regressor, param): plt.title("MSE depending on Algorithm Parameter") plt.xlabel("Algorithm Parameter (k for KNN, Number of Estimators for RF )") -plt.ylabel("MSE") +plt.ylabel("MSE of Power [MW]") plt.xlim([1, 128]) mse_naive_hats = [] diff --git a/examples/prediction/horizon_mse.py b/examples/prediction/horizon_mse.py index 7193a8d..5802a20 100644 --- a/examples/prediction/horizon_mse.py +++ b/examples/prediction/horizon_mse.py @@ -91,8 +91,8 @@ def compute_mse(regressor, horizon): labels = {'linear': 'Linear', 'knn': 'KNN', 'naive' : 'Naive'} plt.title("MSE depending on Forecast Horizon") -plt.xlabel("Forecast Horizon") -plt.ylabel("MSE") +plt.xlabel("Forecast Horizon Time [600s]") +plt.ylabel("MSE of Power [MW]") mse_naive_hats = [] for regressor in regressors: diff --git a/examples/statistics/windspeed_histogram.py b/examples/statistics/windspeed_histogram.py index 4ea1e5c..ee6dd6c 100644 --- a/examples/statistics/windspeed_histogram.py +++ b/examples/statistics/windspeed_histogram.py @@ -11,10 +11,14 @@ import matplotlib.pyplot as plt from pylab import plt from windml.datasets.nrel import NREL +from windml.visualization.colorset import colorset ds = NREL() turbine = ds.get_turbine(NREL.park_id['cheyenne'], 2004) speeds = map(lambda x : x[2], turbine.measurements) -plt.hist(speeds, color="#c4d8eb", bins=10, normed = 1) +plt.title("Histogram of Wind Speeds") +plt.xlabel("Wind Speed [m/s] in time t") +plt.ylabel("Relative Frequency") +plt.hist(speeds, color=colorset[0], bins=10, normed = 1) plt.show() diff --git a/windml/benchmark/benchmark.py b/windml/benchmark/benchmark.py index 4f4a528..227cba9 100644 --- a/windml/benchmark/benchmark.py +++ b/windml/benchmark/benchmark.py @@ -87,10 +87,6 @@ def print_results(self): print "%s MSE: %f" % (park, statistics['mse']) def visualize_mse_on_parks(self): - plt.title("MSE on parks") - plt.xlabel("Park") - plt.ylabel("MSE") - index = arange(len(self.results[self.results.keys()[0]])) bar_width = 0.3 @@ -115,8 +111,8 @@ def visualize_mse_on_parks(self): current_bar = current_bar + 1 plt.xlabel('Park') - plt.ylabel('MSE') - plt.title('MSE by Park') + plt.ylabel('MSE [MW]') + plt.title('MSE [MW] by Park') plt.xticks(index + (current_bar * bar_width) / 2.0,\ park_names) diff --git a/windml/visualization/plot_multiple_timeseries.py b/windml/visualization/plot_multiple_timeseries.py index f6d3174..32168c2 100644 --- a/windml/visualization/plot_multiple_timeseries.py +++ b/windml/visualization/plot_multiple_timeseries.py @@ -72,11 +72,11 @@ def plot_multiple_timeseries(windpark, show = True): poly.set_alpha(0.7) ax.add_collection3d(poly, zs=zs, zdir='y') - ax.set_xlabel('Time') + ax.set_xlabel('Time [600s]') ax.set_xlim3d(0, length) ax.set_ylabel('Turbine') ax.set_ylim3d(-1, number_turbines) - ax.set_zlabel('Power') + ax.set_zlabel('Power [MW]') ax.set_zlim3d(0,30.) plt.title("Time Series Comparison") diff --git a/windml/visualization/plot_timeseries.py b/windml/visualization/plot_timeseries.py index ac557eb..a6732cf 100644 --- a/windml/visualization/plot_timeseries.py +++ b/windml/visualization/plot_timeseries.py @@ -67,7 +67,7 @@ def plot_timeseries(turbine, start, end, show = True): ax.grid(True) plt.ylim(-2, 32) - plt.ylabel("Corrected Power (MW), Wind Speed (m/s)") + plt.ylabel("Corrected Power [MW], Wind Speed [m/s]") plt.plot(d_time[start:end], y1[start:end], label = 'Power Production') plt.plot(d_time[start:end], y2[start:end], label = 'Wind Speed') plt.legend(loc='lower right') From 5176dc5e50a9cdf3c1fdc0077633b60d39af6327 Mon Sep 17 00:00:00 2001 From: Jendrik Poloczek Date: Thu, 14 Nov 2013 15:08:04 +0100 Subject: [PATCH 23/24] updated colors in example --- .../prediction/compare_regressors_param.py | 10 ++++++--- examples/prediction/horizon_mse.py | 10 ++++++--- examples/prediction/knn_regression_turbine.py | 19 ++++++++++------- examples/prediction/lin_regression_turbine.py | 21 +++++++++++-------- .../prediction/response_curve_quartett.py | 12 ++++++----- examples/prediction/svr_regression_turbine.py | 19 ++++++++++------- examples/visualization/sequence.py | 8 ++++--- examples/visualization/wind_embeddings.py | 3 ++- windml/visualization/colorset.py | 19 ++++++++++++++++- windml/visualization/show_flip_book.py | 4 +++- 10 files changed, 85 insertions(+), 40 deletions(-) diff --git a/examples/prediction/compare_regressors_param.py b/examples/prediction/compare_regressors_param.py index 169220d..902da1a 100644 --- a/examples/prediction/compare_regressors_param.py +++ b/examples/prediction/compare_regressors_param.py @@ -23,6 +23,7 @@ from numpy import zeros, float32 from windml.datasets.nrel import NREL from windml.mapping.power_mapping import PowerMapping +from windml.visualization.colorset import colorset from sklearn.grid_search import GridSearchCV from sklearn import linear_model @@ -90,7 +91,8 @@ def compute_mse(regressor, param): regressors = ['rf', 'knn'] params = [1,2,4,8,16,32,64,128] -marker = {'rf': 'go--', 'knn': 'ro--', 'naive': 'bo--'} +color = {'rf': colorset[0], 'knn': colorset[3], 'naive': colorset[2]} +marker = {'rf': 'o--', 'knn': 'o--', 'naive': 'o--'} labels = {'rf': 'Random Forest', 'knn': 'KNN', 'naive' : 'Naive'} plt.title("MSE depending on Algorithm Parameter") @@ -106,9 +108,11 @@ def compute_mse(regressor, param): mse_y_hat, mse_naive_hat = compute_mse(regressor, param) mse.append(mse_y_hat) mse_naive_hats.append(mse_naive_hat) - plt.plot(params, mse, marker[regressor], label=labels[regressor]) + plt.plot(params, mse, marker[regressor], label=labels[regressor],\ + color=color[regressor]) -plt.plot(params, mse_naive_hats, marker['naive'], label=labels['naive']) +plt.plot(params, mse_naive_hats, marker['naive'], label=labels['naive'],\ + color=color['naive']) plt.legend(loc='upper right') plt.show() diff --git a/examples/prediction/horizon_mse.py b/examples/prediction/horizon_mse.py index 5802a20..d50b0d1 100644 --- a/examples/prediction/horizon_mse.py +++ b/examples/prediction/horizon_mse.py @@ -23,6 +23,7 @@ from numpy import zeros, float32 from windml.datasets.nrel import NREL from windml.mapping.power_mapping import PowerMapping +from windml.visualization.colorset import colorset from sklearn.grid_search import GridSearchCV from sklearn import linear_model @@ -87,7 +88,8 @@ def compute_mse(regressor, horizon): regressors = ['linear', 'knn'] horizons = range(2, 18, 2) -marker = {'linear': 'go--', 'knn': 'ro--', 'naive': 'bo--'} +color = {'linear': colorset[0], 'knn': colorset[3], 'naive': colorset[2]} +marker = {'linear': 'o--', 'knn': 'o--', 'naive': 'o--'} labels = {'linear': 'Linear', 'knn': 'KNN', 'naive' : 'Naive'} plt.title("MSE depending on Forecast Horizon") @@ -102,9 +104,11 @@ def compute_mse(regressor, horizon): mse_y_hat, mse_naive_hat = compute_mse(regressor, horizon) mse.append(mse_y_hat) mse_naive_hats.append(mse_naive_hat) - plt.plot(horizons, mse, marker[regressor], label=labels[regressor]) + plt.plot(horizons, mse, marker[regressor], color=color[regressor],\ + label=labels[regressor]) -plt.plot(horizons, mse_naive_hats, marker['naive'], label=labels['naive']) +plt.plot(horizons, mse_naive_hats, marker['naive'], label=labels['naive'],\ + color=color['naive']) plt.legend(loc='lower right') plt.show() diff --git a/examples/prediction/knn_regression_turbine.py b/examples/prediction/knn_regression_turbine.py index f528fab..13041bf 100644 --- a/examples/prediction/knn_regression_turbine.py +++ b/examples/prediction/knn_regression_turbine.py @@ -31,6 +31,7 @@ from numpy import zeros, float32 from windml.datasets.nrel import NREL from windml.mapping.power_mapping import PowerMapping +from windml.visualization.colorset import cmap, colorset from sklearn.neighbors import KNeighborsRegressor # get windpark and corresponding target. forecast is for the target turbine @@ -93,10 +94,14 @@ for i in range(0, len(y_hat)): y[i] = (Y[train_to + (i * test_step)]) +colors = {'predictor' : colorset[0], + 'naive' : colorset[1], + 'true' : colorset[3]} + time = range(0, len(y_hat)) -plt.plot(time, y, "g-", label="Measurement") -plt.plot(time, y_hat, "r-", label="KNN-predicted") -plt.plot(time, naive_hat, "b-", label="Naive-predicted") +plt.plot(time, y, color=colors['true'], label="Measurement") +plt.plot(time, y_hat, color=colors['predictor'], label="KNN-predicted") +plt.plot(time, naive_hat, color=colors['naive'], label="Naive-predicted") plt.xlabel("Time [600s]") plt.ylabel("Power [MW]") plt.xlim([9600, 9750]) @@ -106,7 +111,7 @@ plot_scatter = plt.subplot(2, 2, 2) plt.title("Naive-predicted and True Measurement") col = abs(y - naive_hat) -plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) +plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=cmap) plt.xlabel("True Measurement [MW]") plt.ylabel("Naive-predicted Measurement [MW]") plt.xlim([0, 30]) @@ -114,8 +119,8 @@ plot_abs = plt.subplot(2, 2, 3) plt.title("Absolute Difference") -plt.plot(time, (y_hat - y), "r-", label="KNN-predicted") -plt.plot(time, (naive_hat - y), "b-", label="Naive-predicted") +plt.plot(time, (y_hat - y), color=colors['predictor'], label="KNN-predicted") +plt.plot(time, (naive_hat - y), color=colors['true'], label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-20, 30]) plt.xlabel("Time [600s]") @@ -125,7 +130,7 @@ plot_scatter = plt.subplot(2, 2, 4) plt.title("KNN-predicted and True Measurement") col = abs(y - y_hat) -plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) +plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=cmap) plt.xlabel("True Measurement [MW]") plt.ylabel("KNN-predicted Measurement [MW]") plt.xlim([0, 30]) diff --git a/examples/prediction/lin_regression_turbine.py b/examples/prediction/lin_regression_turbine.py index 8526d81..af8398d 100644 --- a/examples/prediction/lin_regression_turbine.py +++ b/examples/prediction/lin_regression_turbine.py @@ -24,9 +24,9 @@ import math import matplotlib.pyplot as plt - from numpy import zeros, float32 from windml.datasets.nrel import NREL +from windml.visualization.colorset import cmap, colorset from windml.mapping.power_mapping import PowerMapping from sklearn import linear_model @@ -87,10 +87,14 @@ for i in range(0, len(y_hat)): y[i] = (Y[train_to + (i * test_step)]) +colors = {'predictor' : colorset[0], + 'naive' : colorset[1], + 'true' : colorset[3]} + time = range(0, len(y_hat)) -plt.plot(time, y, "g-", label="Measurement") -plt.plot(time, y_hat, "r-", label="Linear-predicted") -plt.plot(time, naive_hat, "b-", label="Naive-predicted") +plt.plot(time, y, color=colors['true'], label="Measurement") +plt.plot(time, y_hat, color=colors['predictor'], label="Linear-predicted") +plt.plot(time, naive_hat, color=colors['naive'], label="Naive-predicted") plt.xlabel("Time [600s]") plt.ylabel("Power [MW]") plt.xlim([9600, 9750]) @@ -100,7 +104,7 @@ plot_scatter = plt.subplot(2, 2, 2) plt.title("Naive-predicted and True Measurement") col = abs(y - naive_hat) -plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) +plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=cmap) plt.xlabel("True Measurement [MW]") plt.ylabel("Naive-predicted Measurement [MW]") plt.xlim([0, 30]) @@ -108,8 +112,8 @@ plot_abs = plt.subplot(2, 2, 3) plt.title("Absolute Difference") -plt.plot(time, (y_hat - y), "r-", label="Linear-predicted") -plt.plot(time, (naive_hat - y), "b-", label="Naive-predicted") +plt.plot(time, (y_hat - y), color=colors['predictor'], label="Linear-predicted") +plt.plot(time, (naive_hat - y), color=colors['true'], label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-20, 30]) plt.xlabel("Time [600s]") @@ -119,7 +123,7 @@ plot_scatter = plt.subplot(2, 2, 4) plt.title("Linear-predicted and True Measurement") col = abs(y - y_hat) -plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) +plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=cmap) plt.xlabel("True Measurement [MW]") plt.ylabel("Linear-predicted Measurement [MW]") plt.xlim([0, 30]) @@ -127,4 +131,3 @@ plt.show() - diff --git a/examples/prediction/response_curve_quartett.py b/examples/prediction/response_curve_quartett.py index 6840662..04582a9 100644 --- a/examples/prediction/response_curve_quartett.py +++ b/examples/prediction/response_curve_quartett.py @@ -25,6 +25,7 @@ from sklearn.neighbors import KNeighborsRegressor from windml.datasets.nrel import NREL from windml.visualization.plot_response_curve import plot_response_curve +from windml.visualization.colorset import colorset ds = NREL() turbine = ds.get_turbine(NREL.park_id['tehachapi'], 2004, 2006) @@ -82,7 +83,7 @@ figure = plt.figure(figsize=(15, 10)) plot_abs = plt.subplot(2, 2, 1) plt.title("Measurements") -plt.scatter(speed, score, color="b") +plt.scatter(speed, score, color=colorset[0]) plt.xlim([-1, max_speed]) plt.xlabel("Windspeed [m/s]") plt.ylim([-2, 32]) @@ -90,7 +91,7 @@ plot_scatter = plt.subplot(2, 2, 2) plt.title("KNN Interpolation of the Response Curve") -plt.plot(T, Y_hat, color='b') +plt.plot(T, Y_hat, color=colorset[0]) plt.scatter(speed, score, color="#CCCCCC") plt.xlim([-1, max_speed]) plt.xlabel("Windspeed [m/s]") @@ -99,7 +100,8 @@ plot_abs = plt.subplot(2, 2, 3) plt.title("Distribution of Wind Speeds") -plt.hist( X_train, bins=np.float(max_speed), histtype='stepfilled', normed=True, color='b') +plt.hist(X_train, bins=np.float(max_speed), histtype='stepfilled',\ + normed=True, color=colorset[0], linewidth=0) plt.xlim([-1, max_speed]) plt.ylim(-0.01, 0.13) plt.xlabel("Windspeed [m/s]") @@ -108,8 +110,8 @@ plot_scatter = plt.subplot(2, 2, 4) plt.title("Frequency of Cut-Outs") steps = range(40) -plt.plot(steps, fraction, "o", color='b') -plt.xlim([-1,max_speed]) +plt.plot(steps, fraction, "o", color=colorset[0], linewidth=0) +plt.xlim([-1, max_speed]) plt.xlabel("Windspeed [m/s]") plt.ylim([-0.1, 1.1]) plt.ylabel("Probabilty of Cut-Out Events (Thres = 15)") diff --git a/examples/prediction/svr_regression_turbine.py b/examples/prediction/svr_regression_turbine.py index e4e0dea..5bba6c7 100644 --- a/examples/prediction/svr_regression_turbine.py +++ b/examples/prediction/svr_regression_turbine.py @@ -34,6 +34,7 @@ from numpy import zeros, float32 from windml.datasets.nrel import NREL from windml.mapping.power_mapping import PowerMapping +from windml.visualization.colorset import cmap, colorset # get windpark and corresponding target. forecast is for the target turbine park_id = NREL.park_id['tehachapi'] @@ -121,10 +122,14 @@ for i in range(0, len(y_hat)): y[i] = (Y[train_to + (i * test_step)]) +colors = {'predictor' : colorset[0], + 'naive' : colorset[1], + 'true' : colorset[3]} + time = range(0, len(y_hat)) -plt.plot(time, y, "g-", label="Measurement") -plt.plot(time, y_hat, "r-", label="SVR-predicted") -plt.plot(time, naive_hat, "b-", label="Naive-predicted") +plt.plot(time, y, color=colors['true'], label="Measurement") +plt.plot(time, y_hat, color=colors['predictor'], label="SVR-predicted") +plt.plot(time, naive_hat, color=colors['naive'], label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-30, 50]) plt.xlabel("Time [600s]") @@ -134,7 +139,7 @@ plot_scatter = plt.subplot(2, 2, 2) plt.title("Naive-predicted and True Measurement") col = abs(y - naive_hat) -plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) +plt.scatter(y, naive_hat, c=col, linewidth=0.0, cmap=cmap) plt.xlabel("True Measurement [MW]") plt.ylabel("Naive-predicted Measurement [MW]") plt.xlim([0, 30]) @@ -142,8 +147,8 @@ plot_abs = plt.subplot(2, 2, 3) plt.title("Absolute Difference") -plt.plot(time, (y_hat - y), "r-", label="SVR-predicted") -plt.plot(time, (naive_hat - y), "b-", label="Naive-predicted") +plt.plot(time, (y_hat - y), color=colors['predictor'], label="SVR-predicted") +plt.plot(time, (naive_hat - y), color=colors['true'], label="Naive-predicted") plt.xlim([9600, 9750]) plt.ylim([-20, 30]) plt.xlabel("Time [600s]") @@ -153,7 +158,7 @@ plot_scatter = plt.subplot(2, 2, 4) plt.title("SVR-predicted and True Measurement") col = abs(y - y_hat) -plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=plt.cm.jet) +plt.scatter(y, y_hat, c=col, linewidth=0.0, cmap=cmap) plt.xlabel("True Measurement [MW]") plt.ylabel("SVR-predicted Measurement [MW]") plt.xlim([0, 30]) diff --git a/examples/visualization/sequence.py b/examples/visualization/sequence.py index 027acd3..a0123a1 100644 --- a/examples/visualization/sequence.py +++ b/examples/visualization/sequence.py @@ -2,9 +2,10 @@ Sequence Visualization Based on ISOMAP ------------------------------------------------------------------------- -This example allows to visualize high-dimensional wind time-series, employing dimensionality reduction. A wind speed sequence is mapped into a -3-dimensional latent space to monitor its intrinsic structure onto one time axis. -The values of the 3-dimensional latent space are normalized and mapped to RGB-values. +This example allows to visualize high-dimensional wind time-series, employing +dimensionality reduction. A wind speed sequence is mapped into a 3-dimensional +latent space to monitor its intrinsic structure onto one time axis. The values +of the 3-dimensional latent space are normalized and mapped to RGB-values. Thereby, the mapping maintains important properties of the original high-dimensional data so that varying wind conditions and seasonal changes can be monitored. @@ -19,6 +20,7 @@ from sklearn import manifold, decomposition from windml.datasets.nrel import NREL +from windml.visualization.colorset import cmap # load data and define parameters / training and test sequences K = 30 diff --git a/examples/visualization/wind_embeddings.py b/examples/visualization/wind_embeddings.py index 704e1c8..694bf23 100644 --- a/examples/visualization/wind_embeddings.py +++ b/examples/visualization/wind_embeddings.py @@ -19,6 +19,7 @@ from sklearn import manifold, datasets, decomposition, lda from windml.visualization.plot_timeseries import plot_timeseries +from windml.visualization.colorset import cmap from windml.datasets.nrel import NREL K = 30 @@ -40,7 +41,7 @@ def plot_embedding(X, title=None, j=1): ax = plt.subplot(2, 2, j) for i in range(X.shape[0]): plt.text(X[i, 0], X[i, 1], str(int(y[i])), - color = plt.cm.jet(y[i] / 30.), + color = cmap(y[i] / 30.), fontdict={'weight': 'bold', 'size': 9}) if title is not None: diff --git a/windml/visualization/colorset.py b/windml/visualization/colorset.py index a81c489..45b24aa 100644 --- a/windml/visualization/colorset.py +++ b/windml/visualization/colorset.py @@ -1 +1,18 @@ -colorset = ["#6699cc","#c4d8eb","#cccccc","#69bb3e","#b8e1a5"] +from pylab import * + +colorset = ["#6698cc","#c4d8eb","#cccccc","#69bb3e","#b8e1a5"] + +cdict = {'red': ((0.0, 0.4, 0.4), + (0.5, 0.72, 0.72), + (1.0, 0.41, 0.41)), + 'green': ((0.0, 0.6, 0.6), + (0.5, 0.88, 0.88), + (1.0, 0.73, 0.73)), + 'blue': ((0.0, 0.8, 0.8), + (0.5, 0.65, 0.65), + (1.0, 0.01, 0.01))} + +0.412, 0.733, 0.012 + +cmap = matplotlib.colors.LinearSegmentedColormap(\ + 'windml_colormap',cdict,256) diff --git a/windml/visualization/show_flip_book.py b/windml/visualization/show_flip_book.py index f8fe1d0..0466ca8 100644 --- a/windml/visualization/show_flip_book.py +++ b/windml/visualization/show_flip_book.py @@ -37,6 +37,7 @@ import time import math from mpl_toolkits.basemap import Basemap, shiftgrid, cm +from windml.visualization.colorset import cmap def show_flip_book(windpark, num_plots, start_time, diff_time, show=True): """Plots a flip book of a given windpark @@ -124,7 +125,8 @@ def show_flip_book(windpark, num_plots, start_time, diff_time, show=True): m.drawmeridians(meridians,labels=[True,False,False,True]) m.shadedrelief() m.drawcoastlines - m.scatter(rel_inputs_lon, rel_inputs_lat, c = zlist, s = 35, vmin = 0.0, vmax = 35) + m.scatter(rel_inputs_lon, rel_inputs_lat, c = zlist, s = 35, vmin = 0.0, vmax = 35,\ + cmap=cmap) plt.title(datetime.datetime.fromtimestamp(unix_timestamps[i-1]).strftime('%Y-%m-%d %H:%M:%S')) plt.colorbar() From 7abb28da3dec04ce6105c7910295f7ca6c2a7725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bengt=20L=C3=BCers?= Date: Tue, 17 Dec 2013 23:19:38 +0100 Subject: [PATCH 24/24] create minimal setup.py to enable installation via pip --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 setup.py diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..79e29cb --- /dev/null +++ b/setup.py @@ -0,0 +1,5 @@ +from setuptools import setup, find_packages + +setup(name='windml', + packages=find_packages(exclude=['examples', 'tests']), + include_package_data=True)