我想预测一些价值 我试图得到一些预测 在尽可能低但仍大于 . 换句话说:
我认为一个简单的线性回归应该做得很好。所以我有点知道如何手动实现这个,但我想我不是第一个遇到这种问题的人。是否有任何软件包/库(最好是 python)在做我想做的事情?我需要查找的关键字是什么?
如果我知道一个函数其中。实施这些限制的最佳方式是什么?
我想预测一些价值 我试图得到一些预测 在尽可能低但仍大于 . 换句话说:
我认为一个简单的线性回归应该做得很好。所以我有点知道如何手动实现这个,但我想我不是第一个遇到这种问题的人。是否有任何软件包/库(最好是 python)在做我想做的事情?我需要查找的关键字是什么?
如果我知道一个函数其中。实施这些限制的最佳方式是什么?
如果我对您的理解正确,那么您想在高估方面犯错。如果是这样,您需要一个适当的非对称成本函数。一个简单的候选方法是调整平方损失:
其中是一个参数,您可以使用它来权衡低估与高估的惩罚。α的正值会惩罚高估,因此您需要将设置为负值。在 python 中,这看起来像def loss(x, a): return x**2 * (numpy.sign(x) + a)**2
接下来让我们生成一些数据:
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))
最后,我们将在tensorflow
Google 的机器学习库 中进行回归,该库支持自动微分(使此类问题的基于梯度的优化更简单)。我将使用这个示例作为起点。
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
是正则平方误差,而acost
是前面提到的不对称损失函数。
如果你使用cost
你会得到
1.00764 -3.32445
如果你使用acost
你会得到
1.02604 -1.07742
acost
显然尽量不要低估。我没有检查收敛,但你明白了。
@Emre 的解决方案非常有趣。因此,我尝试使用@Emre 提出的成本函数并从头开始编写代码以拟合线性回归。对于那些不想使用 Tensorflow 的人来说,它可能很有用。这是我的代码:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_regression
# generate regression dataset
X, y = make_regression(n_samples=100, n_features=1, noise=30)
def cost_MSE(y_true, y_pred, a = 0):
'''
Cost function
'''
# Shape of the dataset
n = y_true.shape[0]
# Error
error = y_true - y_pred
# Compute the sign part of the loss function
signs = np.sign(error) + a
# Cost
mse = np.dot(np.multiply(error, error), np.multiply(signs, signs)) / n
return mse
def cost_derivative(X, y_true, y_pred, a = 0):
'''
Compute the derivative of the loss function
'''
# Shape of the dataset
n = y_true.shape[0]
# Error
error = y_true - y_pred
# Compute the sign part of the loss function
signs = np.sign(error) + a
# Compute the sign part of the loss function
signs = np.multiply(signs, signs)
# Derivative
der = -2 / n * np.dot(np.multiply(X, error), signs)
return der
# Lets run an example
X_new = np.concatenate((np.ones(X.shape), X), axis = 1)
learning_rate = 0.1
X_new_T = X_new.T
n_iters = 20
# this variable is used to adjust the degree of underestimation or overestimation
# please take a look at the attached figure for more clarification.
# if a = 0 >>> no underestimation or overestimation
a = 0
mse = []
#initialize the weight vector
alpha = np.array([0, np.random.rand()])
for _ in range(n_iters):
# Compute the predicted y
y_pred = np.dot(X_new, alpha)
# Compute the MSE
mse.append(cost_MSE(y, y_pred, a))
# Compute the derivative
der = cost_derivative(X_new_T, y, y_pred, a)
# Update the weight
alpha -= learning_rate * der
这也是我在不同场景下的结果。
如果您有任何意见,请告诉我。我会将您的评论应用于代码并更新答案。
选择一个不对称的损失函数。一种选择是分位数回归(线性但正负误差的斜率不同)。