Regresja liniowa z niesymetryczną funkcją kosztu?

13

Chcę przewidzieć pewną wartość i próbuję uzyskać prognozę która optymalizuje między byciem tak niskim, jak to możliwe, ale wciąż większym niż . Innymi słowy: Y(x)Y^(x)Y(x)

cost{Y(x)Y^(x)}>>cost{Y^(x)Y(x)}

Myślę, że prosta regresja liniowa powinna dać sobie radę. Wiem więc trochę, jak zaimplementować to ręcznie, ale chyba nie jestem pierwszym, który ma tego rodzaju problemy. Czy są jakieś pakiety / biblioteki (najlepiej Python), które robią to, co chcę? Jakiego słowa kluczowego muszę szukać?

Co, jeśli znałbym funkcję Y_0 (x)> 0,Y0(x)>0 gdzie Y(x)>Y0(x) . Jaki jest najlepszy sposób na wdrożenie tych ograniczeń?

asPlankBridge
źródło
Prawdopodobnie najprostszym rozwiązaniem jest użycie różnych wag w zależności od tego, czy prognoza jest dodatnia czy ujemna. Powinienem był o tym pomyśleć wcześniej.
asPlankBridge

Odpowiedzi:

11

Jeśli dobrze cię rozumiem, chcesz się mylić po stronie przeszacowania. Jeśli tak, potrzebujesz odpowiedniej, asymetrycznej funkcji kosztu. Jednym prostym kandydatem jest poprawienie straty do kwadratu:

L:(x,α)x2(sgnx+α)2

gdzie jest parametrem, którego możesz użyć, aby wymienić karę niedoszacowania na przeszacowanie. Dodatnie wartości penalizują przeszacowanie, więc będziesz chciał ustawić ujemny. W Pythonie wygląda to tak1<α<1ααdef loss(x, a): return x**2 * (numpy.sign(x) + a)**2

Funkcje strat dla dwóch wartości a

Następnie wygenerujmy trochę danych:

import numpy
x = numpy.arange(-10, 10, 0.1)
y = -0.1*x**2 + x + numpy.sin(x) + 0.1*numpy.random.randn(len(x))

Funkcja arbitralna

Na koniec dokonamy regresji w tensorflowbibliotece uczenia maszynowego od Google, która obsługuje automatyczne różnicowanie (upraszczając optymalizację takich problemów na podstawie gradientu). Wykorzystam ten przykład jako punkt wyjścia.

import tensorflow as tf

X = tf.placeholder("float") # create symbolic variables
Y = tf.placeholder("float") 

w = tf.Variable(0.0, name="coeff")
b = tf.Variable(0.0, name="offset")
y_model = tf.mul(X, w) + b

cost = tf.pow(y_model-Y, 2) # use sqr error for cost function
def acost(a): return tf.pow(y_model-Y, 2) * tf.pow(tf.sign(y_model-Y) + a, 2)

train_op = tf.train.AdamOptimizer().minimize(cost)
train_op2 = tf.train.AdamOptimizer().minimize(acost(-0.5))

sess = tf.Session()
init = tf.initialize_all_variables()
sess.run(init)

for i in range(100):
    for (xi, yi) in zip(x, y): 
#         sess.run(train_op, feed_dict={X: xi, Y: yi})
        sess.run(train_op2, feed_dict={X: xi, Y: yi})

print(sess.run(w), sess.run(b))

costjest regularnym błędem do kwadratu, podczas gdy acostjest wspomnianą funkcją asymetrycznej straty.

Jeśli użyjesz cost, otrzymasz

1,00764 -3,32445

koszt

Jeśli użyjesz acost, otrzymasz

1,02604 -1,07742

koszt

acostwyraźnie stara się nie lekceważyć. Nie sprawdziłem zbieżności, ale masz pomysł.

Emre
źródło
Dziękuję za tę szczegółową odpowiedź: jedno pytanie do definicji acostfunkcji. Czy to ważne, że obliczasz y_model-Ydwa razy?
asPlankBridge
Masz na myśli prędkość? Nie wiem; będziesz musiał sam to sprawdzić, czy tensorflow unika ponownego obliczenia. W przeciwnym razie jest w porządku.
Emre
0

Wybierz asymetryczną funkcję straty. Jedną z opcji jest regresja kwantylowa (liniowa, ale o różnych nachyleniach dla błędów dodatnich i ujemnych).

Brian Spiering
źródło