Skip to content

Commit caef584

Browse files
author
Paul Masurel
committed
Added quantile regression as possible final MLP Layer.
closes #1549
1 parent a303ec1 commit caef584

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

pylearn2/models/mlp.py

+43
Original file line numberDiff line numberDiff line change
@@ -3824,6 +3824,49 @@ def L1WeightDecay(*args, **kwargs):
38243824
return _L1WD(*args, **kwargs)
38253825

38263826

3827+
class QuantileRegression(Linear):
3828+
"""
3829+
A linear layer for quantile regression.
3830+
3831+
A QuantileRegression (http://en.wikipedia.org/wiki/Quantile_regression)
3832+
is a linear layer that uses a specific cost that makes it possible to get
3833+
an estimator of a specific percentile of a posterior distribution.
3834+
3835+
Parameters
3836+
----------
3837+
layer_name: str
3838+
The layer name
3839+
percentile: float (0 < percentile < 1)
3840+
Percentile being estimated.
3841+
3842+
"""
3843+
def __init__(self,
3844+
layer_name,
3845+
percentile=0.2,
3846+
**kargs):
3847+
Linear.__init__(self, 1, layer_name, **kargs)
3848+
self.percentile = percentile
3849+
3850+
@wraps(Layer.get_layer_monitoring_channels)
3851+
def get_layer_monitoring_channels(self,
3852+
state_below=None,
3853+
state=None,
3854+
targets=None):
3855+
rval = Linear.get_layer_monitoring_channels(
3856+
self,
3857+
state_below,
3858+
state,
3859+
targets)
3860+
assert isinstance(rval, OrderedDict)
3861+
if targets:
3862+
rval['qcost'] = (T.abs_(targets - state) * (0.5 + (self.percentile - 0.5) * T.sgn(targets - state) )).mean()
3863+
return rval
3864+
3865+
@wraps(Layer.cost_matrix)
3866+
def cost_matrix(self, Y, Y_hat):
3867+
return T.abs_(Y - Y_hat) * (0.5 + (self.percentile - 0.5) * T.sgn(Y - Y_hat) )
3868+
3869+
38273870
class LinearGaussian(Linear):
38283871

38293872
"""

pylearn2/models/tests/test_mlp.py

+36
Original file line numberDiff line numberDiff line change
@@ -1389,3 +1389,39 @@ def test_pooling_with_anon_variable():
13891389
image_shape=im_shp, try_dnn=False)
13901390
pool_1 = mean_pool(X_sym, pool_shape=shp, pool_stride=strd,
13911391
image_shape=im_shp)
1392+
1393+
1394+
1395+
def test_quantile_regression():
1396+
"""
1397+
Create a VectorSpacesDataset with two inputs (features0 and features1)
1398+
and train an MLP which takes both inputs for 1 epoch.
1399+
"""
1400+
np.random.seed(2)
1401+
nb_rows = 1000
1402+
X = np.random.normal(size=(nb_rows, 2)).astype(theano.config.floatX)
1403+
noise = np.random.rand(nb_rows, 1) # X[:, 0:1] *
1404+
coeffs = np.array([[3.], [4.]])
1405+
y_0 = np.dot(X, coeffs)
1406+
y = y_0 + noise
1407+
dataset = DenseDesignMatrix(X=X, y=y)
1408+
for percentile in [0.22, 0.5, 0.65]:
1409+
mlp = MLP(
1410+
nvis=2,
1411+
layers=[
1412+
QuantileRegression('quantile_regression_layer',
1413+
init_bias=0.0,
1414+
percentile=percentile,
1415+
irange=0.1)
1416+
]
1417+
)
1418+
train = Train(dataset, mlp, SGD(0.05, batch_size=100))
1419+
train.algorithm.termination_criterion = EpochCounter(100)
1420+
train.main_loop()
1421+
inputs = mlp.get_input_space().make_theano_batch()
1422+
outputs = mlp.fprop(inputs)
1423+
y_ = theano.function([inputs], outputs, allow_input_downcast=True)(X)
1424+
layers = mlp.layers
1425+
layer = layers[0]
1426+
assert np.allclose(layers[0].get_weights(), coeffs, rtol=0.05)
1427+
assert np.allclose(layers[0].get_biases(), np.array(percentile), rtol=0.05)

0 commit comments

Comments
 (0)