我稍微修改了您的代码。现在通过两种方式解决拟合:作为简单的梯度下降和通过 scipy 优化器。梯度下降非常慢,不应该用于实际问题。我在 Coursera 的机器学习课程中获取的数据对课程进行了测试
我不确定我是否可以共享原始数据集。这是它的一个简短片段:
34.62365962451697,78.0246928153624,0
30.28671076822607,43.89499752400101,0
35.84740876993872,72.90219802708364,0
60.18259938620976,86.30855209546826,1
79.0327360507101,75.3443764369103,1
45.08327747668339,56.3163717815305,0
61.10666453684766,96.51142588489624,1
以下是两个解决方案的输出:
简单梯度下降(经过 100000 次迭代...)
Number of Features: 3
Found Solution:
[[-4.81180027]
[ 0.04528064]
[ 0.03819149]]
Train Accuracy: 0.910000
Scipy 优化器(非常快)
Number of Features: 3
Found Solution:
[[-25.16131869]
[ 0.20623159]
[ 0.20147149]]
Train Accuracy: 0.890000
此代码中的决策边界仅适用于相同类型的问题(分隔两组的直线)。为了获得更高的准确性,您可以尝试将特征组合作为新特征(注意可能的过度拟合)。
代码如下:
import numpy as np
from numpy import *
import scipy.optimize as op
import matplotlib.pyplot as plt
class Logisticr():
def __init__(self, X, y, alg, eta, w):
self.X = X
self.y = y
self.alg = alg
self.eta = eta
self.w = w
self.m, self.n = np.shape(X)
def sigFunc(self, z):
return 1.0 / (1.0 + np.exp( -z ))
def decide(self, x):
return np.where(x >= 0.5, 1, 0)
def costfunc(self, w, X, y):
w = w.reshape((self.n,1))
z = X * w
phi =self.sigFunc(z)
# calculating the cost function
part1 = np.multiply(y, np.log(phi))
part2 = np.multiply((1 - y), np.log(1 - phi))
J = (-part1 - part2).sum()/self.m
# calculating the gradient
grad = X.T * (phi - y) / self.m
return J, grad
def graddescent(self, maxiter):
for i in range(0, maxiter):
J, grad = self.costfunc(self.w, self.X, self.y)
self.w = self.w - self.eta*grad
return self.w
def fit(self):
print "Number of Features: %d" %self.n
if self.alg == 0:
_maxiter = 100000
self.w = self.graddescent(_maxiter)
else:
Result = op.minimize(fun = self.costfunc,
x0 = self.w,
args = (self.X, self.y),
method = 'TNC',
jac = True);
self.w = Result.x
self.w = np.matrix(self.w).T
print "Found Solution:"
print self.w
z = self.X * self.w
phi = self.sigFunc(z)
correctAnswer = np.where(np.array(self.y == self.decide(phi)) == True, 1, 0)
accuracy = float(sum(correctAnswer)) / len(correctAnswer)
print "Train Accuracy: %f" %accuracy
def plot(self):
if self.n == 3:
ind_1 = np.where(self.y == 1)
ind_0 = np.where(self.y == 0)
x1_1 = self.X[:, [1]].min()
x1_2 = self.X[:, [1]].max()
x2_1 = -(self.w[0, 0] + self.w[1, 0]*x1_1)/self.w[2, 0]
x2_2 = -(self.w[0, 0] + self.w[1, 0]*x1_2)/self.w[2, 0]
plt.plot(self.X[ind_1, [1]], self.X[ind_1, [2]], "bo", markersize=3)
plt.plot(self.X[ind_0, [1]], self.X[ind_0, [2]], "ro", markersize=3)
plt.plot([x1_1, x1_2], [x2_1, x2_2], "g-")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.title("Decision boundary")
plt.show()
return 1
# Main module
_f = loadtxt('data/ex2data1.txt', delimiter=',')
_X, _y = _f[:,[0,1]], _f[:,[2]]
_m = np.shape(_X)[0]
# add a column of 1
_X = np.hstack((np.matrix(np.ones((_m, 1))),_X))
_y = np.matrix(_y)
_alg = 1 # 0 = using simple gradient descent
# 1 = using an optimizer
_eta = 0.001 # initial eta value for _type = 0
_n= np.shape(_X)[1]
_w = np.matrix(np.zeros((_n, 1)))
# creating an instance of the Logisticr
lr = Logisticr(_X, _y, _alg, _eta, _w);
lr.fit()
lr.plot()
更新
我尝试使用引用的数据集。在我看来,仅使用温度和湿度不能很好地分离这些类。即使您使用高阶特征组合,您也可能会过度拟合分类器。你不这么认为吗?