Logistic Regression——二分类
概念:
分类算法是一种典型的监督学习算法,数据标签为离散值,比如{0,1},而我们所要做的任务就是通过数据集的训练,让算法能够预测下一组数据为另外一个值的概率。
步骤:
前面的gradient descent 介绍了我们的一般方法,我们继续以此步骤完成我们的二分类算法。
在此之前,我们需要将数据集进行分类,例如:有和没有等等对立的元素用{0,1}来表征,这里就需要引入阈值函数,sigmoid
它的函数图像如下:
它在0和一之间的变化趋势很大,同时值域在[0,1],因此可以很好的区分样本。
画出图像曲线:
加载数据:
data = np.loadtxt('ex2data1.txt', delimiter=',')
X = data[:, 0:2]
y = data[:, 2]
首先根据数据集编写代码画出它的函数图像:
# plot data
def plotData(X, y):
X_1 = X[y == 1]
X_0 = X[y == 0]
plt.plot(X_1[:, 0], X_1[:, 1], 'k+')
plt.plot(X_0[:, 0], X_0[:, 1], 'yo')
plt.legend(['Admitted', 'Not admitted'])
输出结果如下:
由上图可以有一个边界将两个样本分割成两个不同的部分,而我们接下来的任务就是将这条曲线给求出来,并通过它预测下一组数组的label。
求出分割近似曲线:
同上篇文一般,我们需要先求出它的cost function,只是与线性回归不同,此次我们求的曲线如下:
可以看出它是一种非线性的表达,其中的代表着权重矩阵的转置,同样x也是一个特征向量的矩阵,此时的损失函数自然不可以像线性回归一样,直接通过标签的值进行相减,因为那样计算出来的值是相当复杂的,同时它也是一个非凸函数,会有很多的局部最优解,此时我们可以使用log函数将它进行凸函数化,所以,新的损失函数如下:
我们来解释一下这个损失函数的含义,我们已经知道的值域在[0,1]之间(见上面的函数图像),那么根据log函数的函数图像:
注意我们这边的log函数其实是ln函数
参照函数图像可知,当我们的定义域,亦即的值不断趋向于1时,它的值的变化程度变缓,也就是说得出来的情况越好,那么我们的损失值越小。这十分符合我们对损失函数的定义。下式亦然。
但是上式其实可以整合成一个式子,如下:
上下两种形式都是等价的,可自行推导。
梯度下降求出权重矩阵:
首先编写出sigmoid函数:
def sigmoid(z):
return 1 / (1 + np.exp(-z))
其中的theta需要每次进行更新,最后得到一个最符号结果的向量集,而更新的依据就是损失函数,costfunction
def costFunction(initial_theta, X, y):
J = 0
grad = np.zeros(np.size(initial_theta, ))
z = X.dot(initial_theta)
J = 1 / m * (-y.dot(np.log(sigmoid(z))) - ((1 - y).dot(np.log(1 - sigmoid(z)))))
grad = 1 / m * (X.T.dot(sigmoid(z) - y))
return J, grad
由于普通的梯度下降可能需要运行很多次,所以我们直接调用函数库来实现快速收敛(与matlab代码有差异)
result = op.minimize(fun=costFunction, x0=initial_theta, args=(X, Y), method='TNC', jac=gradient)
很快的得到权重矩阵:
通过矩阵我们就可以绘制边界了:
绘制边界:
def plotDecisionBoundary(theta, x, y):
pos = np.where(y == 1)
neg = np.where(y == 0)
p1 = plt.scatter(x[pos, 1], x[pos, 2], marker='+', s=60, color='r')
p2 = plt.scatter(x[neg, 1], x[neg, 2], marker='o', s=60, color='y')
plot_x = np.array([np.min(x[:, 1])-2, np.max(x[:, 1]+2)])
plot_y = -1/theta[2]*(theta[1]*plot_x+theta[0])
plt.plot(plot_x, plot_y)
plt.legend((p1, p2), ('Admitted', 'Not admitted'), loc='upper right', fontsize=8)
plt.xlabel('Exam 1 score')
plt.ylabel('Exam 2 score')
plt.show()
预测与正确率:
def predict(theta, x):
return np.round(sigmoid(x.dot(theta)))
print('Train Accuracy: %f', np.mean(np.double(p == y)) * 100)
全部代码:
部分代码参考:
ning/blob/wrong/Logistic%20Regression/Logistic%20Regression-reset.py)
部分代码参考: