向量功能Logistic回归的成本函数输出不正确

时间:2018-08-22 15:55:05

标签: python-3.x numpy logistic-regression

我正在尝试对Iris数据集实施矢量化逻辑回归。这是Andrew Ng的youtube系列关于深度学习的实现。使用此方法的最佳预测是81%的精度,而sklearn的实现可以通过完全不同的系数和偏差值实现100%的精度。另外,我似乎无法从成本函数中获得适当的输出。我怀疑计算成本函数的权重和偏差的梯度是个问题,尽管在此过程中他提供了所有必要的方程式(除非在实际练习中有些东西我无法获得)省略。)我的代码如下。

n = 4
m = 150

y = y.reshape(1, 150)
X = X.reshape(4, 150)
W = np.zeros((4, 1))
b = np.zeros((1,1))

for epoch in range(1000):
    Z = np.dot(W.T, X) + b
    A = sigmoid(Z)                                           # 1/(1 + e **(-Z))
    J = -1/m * np.sum(y * np.log(A) + (1-y) * (1 - np.log(A)))   #cost function
    dz = A - y
    dw = 1/m * np.dot(X, dz.T)
    db = np.sum(dz)
    W = W - 0.01 * dw 
    b = b - 0.01 * db

    if epoch % 100 == 0:
        print(J)

我的输出看起来像这样。

   -1.6126604413879289
   -1.6185960074767125
   -1.6242504226045396
   -1.6296400635926438
   -1.6347800862216104
   -1.6396845400653066
   -1.6443664703028427
   -1.648838008214648
   -1.653110451818512
   -1.6571943378913891

W和b值为:

  array([[-0.68262679, -1.56816916,  0.12043066,  1.13296948]])
  array([[0.53087131]])

sklearn输出为

  (array([[ 0.41498833,  1.46129739, -2.26214118, -1.0290951 ]]),
   array([0.26560617]))

我了解sklearn使用L2正则化功能,但即使将其关闭也仍然与正确的值相差甚远。任何帮助,将不胜感激。谢谢

1 个答案:

答案 0 :(得分:1)

您可能会得到奇怪的结果,因为您尝试使用Logistic回归,其中y不是二进制选择。对虹膜数据进行分类是一个多类问题,y可以是以下三个值之一:

> np.unique(iris.target)
> array([0, 1, 2])

交叉熵代价函数期望y 为1或0。一种解决此问题的方法是“一对多”方法。

您可以通过使y为一个布尔值来确定虹膜是否属于一个类,以检查每个类。例如,在这里您可以使y为1类或非1类的数据集:

y = (iris.target == 1).astype(int)

因此,您的成本函数和梯度下降应该可以工作,但是您需要多次运行它,并为每个示例选择最佳分数。 Andrew Ng's class talks about this method.

编辑:

目前尚不清楚您是从什么开始获取数据的。当我这样做时,不要重塑输入。因此,您应该仔细检查所有乘法是否都可以提供所需的形状。我注意到这有点奇怪,它是成本函数中的最后一项。我通常这样做:

cost = -1/m * np.sum(Y*np.log(A) + (1-Y) * np.log(1-A))

不是:

-1/m * np.sum(y * np.log(A) + (1-y) * (1 - np.log(A)))

以下是使用sklearn中的数据集为我收敛的代码:

from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
# Iris is a multiclass problem. Here, just calculate the probabily that
# the class is `iris_class`
iris_class = 0
Y = np.expand_dims((iris.target == iris_class).astype(int), axis=1)
# Y is now a data set of booleans indicating whether the sample is or isn't a member of iris_class

# initialize w and b
W = np.random.randn(4, 1)
b = np.random.randn(1, 1)

a = 0.1              # learning rate
m = Y.shape[0]        # number of samples

def sigmoid(Z):
    return 1/(1 + np.exp(-Z))

for i in range(1000):
    Z = np.dot(X ,W) + b
    A = sigmoid(Z)
    dz = A - Y
    dw = 1/m * np.dot(X.T, dz)
    db = np.mean(dz)
    W -= a * dw
    b -= a * db
    cost = -1/m * np.sum(Y*np.log(A) + (1-Y) * np.log(1-A))

    if i%100 == 0:
        print(cost)