<s> from GPy . core . mapping import Mapping <EOL> from GPy . core import Param <EOL> import numpy as np <EOL> class PiecewiseLinear ( Mapping ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , input_dim , output_dim , values , breaks , name = '<STR_LIT>' ) : <EOL> assert input_dim == <NUM_LIT:1> <EOL> assert output_dim == <NUM_LIT:1> <EOL> Mapping . __init__ ( self , input_dim , output_dim , name ) <EOL> values , breaks = np . array ( values ) . flatten ( ) , np . array ( breaks ) . flatten ( ) <EOL> assert values . size == breaks . size <EOL> self . values = Param ( '<STR_LIT>' , values ) <EOL> self . breaks = Param ( '<STR_LIT>' , breaks ) <EOL> self . link_parameter ( self . values ) <EOL> self . link_parameter ( self . breaks ) <EOL> def parameters_changed ( self ) : <EOL> self . order = np . argsort ( self . breaks ) * <NUM_LIT:1> <EOL> self . reverse_order = np . zeros_like ( self . order ) <EOL> self . reverse_order [ self . order ] = np . arange ( self . order . size ) <EOL> self . sorted_breaks = self . breaks [ self . order ] <EOL> self . sorted_values = self . values [ self . order ] <EOL> self . grads = np . diff ( self . sorted_values ) / np . diff ( self . sorted_breaks ) <EOL> def f ( self , X ) : <EOL> x = X . flatten ( ) <EOL> y = x . copy ( ) <EOL> y [ x < self . sorted_breaks [ <NUM_LIT:0> ] ] = x [ x < self . sorted_breaks [ <NUM_LIT:0> ] ] + self . sorted_values [ <NUM_LIT:0> ] - self . sorted_breaks [ <NUM_LIT:0> ] <EOL> y [ x > self . sorted_breaks [ - <NUM_LIT:1> ] ] = x [ x > self . sorted_breaks [ - <NUM_LIT:1> ] ] + self . sorted_values [ - <NUM_LIT:1> ] - self . sorted_breaks [ - <NUM_LIT:1> ] <EOL> for low , up , g , v in zip ( self . sorted_breaks [ : - <NUM_LIT:1> ] , self . sorted_breaks [ <NUM_LIT:1> : ] , self . grads , self . sorted_values [ : - <NUM_LIT:1> ] ) : <EOL> i = np . logical_and ( x > low , x < up ) <EOL> y [ i ] = v + ( x [ i ] - low ) * g <EOL> return y . reshape ( - <NUM_LIT:1> , <NUM_LIT:1> ) <EOL> def update_gradients ( self , dL_dF , X ) : <EOL> x = X . flatten ( ) <EOL> dL_dF = dL_dF . flatten ( ) <EOL> dL_db = np . zeros ( self . sorted_breaks . size ) <EOL> dL_dv = np . zeros ( self . sorted_values . size ) <EOL> for i , ( low , up , g , v ) in enumerate ( zip ( self . sorted_breaks [ : - <NUM_LIT:1> ] , self . sorted_breaks [ <NUM_LIT:1> : ] , self . grads , self . sorted_values [ : - <NUM_LIT:1> ] ) ) : <EOL> index = np . logical_and ( x > low , x < up ) <EOL> xx = x [ index ] <EOL> grad = dL_dF [ index ] <EOL> span = up - low <EOL> dL_dv [ i ] += np . sum ( grad * ( ( low - xx ) / span + <NUM_LIT:1> ) ) <EOL> dL_dv [ i + <NUM_LIT:1> ] += np . sum ( grad * ( xx - low ) / span ) <EOL> dL_db [ i ] += np . sum ( grad * g * ( xx - up ) / span ) <EOL> dL_db [ i + <NUM_LIT:1> ] += np . sum ( grad * g * ( low - xx ) / span ) <EOL> dL_db [ <NUM_LIT:0> ] -= np . sum ( dL_dF [ x < self . sorted_breaks [ <NUM_LIT:0> ] ] ) <EOL> dL_db [ - <NUM_LIT:1> ] -= np . sum ( dL_dF [ x > self . sorted_breaks [ - <NUM_LIT:1> ] ] ) <EOL> dL_dv [ <NUM_LIT:0> ] += np . sum ( dL_dF [ x < self . sorted_breaks [ <NUM_LIT:0> ] ] ) <EOL> dL_dv [ - <NUM_LIT:1> ] += np . sum ( dL_dF [ x > self . sorted_breaks [ - <NUM_LIT:1> ] ] ) <EOL> self . breaks . gradient = dL_db [ self . reverse_order ] <EOL> self . values . gradient = dL_dv [ self . reverse_order ] <EOL> def gradients_X ( self , dL_dF , X ) : <EOL> x = X . flatten ( ) <EOL> dL_dX = dL_dF . copy ( ) . flatten ( ) <EOL> for low , up , g , v in zip ( self . sorted_breaks [ : - <NUM_LIT:1> ] , self . sorted_breaks [ <NUM_LIT:1> : ] , self . grads , self . sorted_values [ : - <NUM_LIT:1> ] ) : <EOL> i = np . logical_and ( x > low , x < up ) <EOL> dL_dX [ i ] = dL_dF [ i ] * g <EOL> return dL_dX . reshape ( - <NUM_LIT:1> , <NUM_LIT:1> ) </s>
