我正在尝试对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正则化功能,但即使将其关闭也仍然与正确的值相差甚远。任何帮助,将不胜感激。谢谢
答案 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)