Si je vous comprends bien, vous voulez pécher par excès de valeur. Si tel est le cas, vous avez besoin d'une fonction de coût asymétrique appropriée. Un candidat simple consiste à modifier la perte au carré:
L :(x, α ) → x2( s g n x + α )2
où est un paramètre que vous pouvez utiliser pour échanger la pénalité de la sous-estimation contre la surestimation. Les valeurs positives de pénalisent la surestimation, vous voudrez donc définir négatif. En python, cela ressemble à- 1 < α < 1ααdef loss(x, a): return x**2 * (numpy.sign(x) + a)**2
Générons ensuite des données:
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))
Enfin, nous ferons notre régression dans tensorflow
, une bibliothèque d'apprentissage automatique de Google qui prend en charge la différenciation automatisée (ce qui simplifie l'optimisation basée sur le gradient de ces problèmes). Je vais utiliser cet exemple comme point de départ.
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))
cost
est l'erreur quadratique régulière, tandis que acost
la fonction de perte asymétrique susmentionnée.
Si vous utilisez, cost
vous obtenez
1,00764 -3,32445
Si vous utilisez, acost
vous obtenez
1.02604 -1.07742
acost
essaie clairement de ne pas sous-estimer. Je n'ai pas vérifié la convergence, mais vous avez compris.