Logistic Regression-修正

Logistic Regression——二分类

概念:

​ 分类算法是一种典型的监督学习算法,数据标签为离散值,比如{0,1},而我们所要做的任务就是通过数据集的训练,让算法能够预测下一组数据为另外一个值的概率。


步骤:

​ 前面的gradient descent 介绍了我们的一般方法,我们继续以此步骤完成我们的二分类算法。

​ 在此之前,我们需要将数据集进行分类,例如:有和没有等等对立的元素用{0,1}来表征,这里就需要引入阈值函数,sigmoid
f ( x ) = 1 1 + e − x f(x) = \frac{1}{1+e^{-x}} f(x)=1+ex1
它的函数图像如下:

image-20210606141551215

它在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'])

输出结果如下:

lg-reset-data1

由上图可以有一个边界将两个样本分割成两个不同的部分,而我们接下来的任务就是将这条曲线给求出来,并通过它预测下一组数组的label。


求出分割近似曲线:

​ 同上篇文一般,我们需要先求出它的cost function,只是与线性回归不同,此次我们求的曲线如下:
f ( x ) = 1 1 + e − θ T x f(x) = \frac{1}{1+e^{-\theta^Tx}} f(x)=1+eθTx1
可以看出它是一种非线性的表达,其中的 θ T \theta^{T} θT代表着权重矩阵的转置,同样x也是一个特征向量的矩阵,此时的损失函数自然不可以像线性回归一样,直接通过标签的值进行相减,因为那样计算出来的值是相当复杂的,同时它也是一个非凸函数,会有很多的局部最优解,此时我们可以使用log函数将它进行凸函数化,所以,新的损失函数如下:
C o s t ( h θ ( x ) , y ) = { − l o g ( h θ ( x ) ) i f y = 1 − l o g ( 1 − h θ ( x ) ) i f y = 0 Cost(h_\theta(x),y) = \begin{cases}-log(h_\theta(x))&ify=1 \\-log(1-h_\theta(x))&ify=0\end{cases} Cost(hθ(x),y)={log(hθ(x))log(1hθ(x))ify=1ify=0

J ( θ ) = − 1 m ∑ C o s t ( h θ ( x ) , y ) J(\theta) = -\frac{1}{m}\sum Cost(h_\theta(x), y) J(θ)=m1Cost(hθ(x),y)

我们来解释一下这个损失函数的含义,我们已经知道 h θ ( x ) h_\theta(x) hθ(x)的值域在[0,1]之间(见上面的函数图像),那么根据log函数的函数图像:

file_img/20210608143204.png  0 → 100644

注意我们这边的log函数其实是ln函数

​ 参照函数图像可知,当我们的定义域,亦即 h θ ( x ) h_\theta(x) hθ(x)的值不断趋向于1时,它的值的变化程度变缓,也就是说得出来的情况越好,那么我们的损失值越小。这十分符合我们对损失函数的定义。下式亦然。

但是上式其实可以整合成一个式子,如下:
C o s t ( h θ ( x ) , y ) = y i l o g ( h θ ( x i ) ) + ( 1 − y i ) ( 1 − l o g ( 1 − h θ ( x i ) ) ) Cost(h_\theta(x),y) = y^{i}log(h_\theta(x^{i})) + (1-y^{i})(1-log(1-h_\theta(x^{i}))) Cost(hθ(x),y)=yilog(hθ(xi))+(1yi)(1log(1hθ(xi)))

J ( θ ) = − 1 m ∑ C o s t ( h θ ( x ) , y ) J(\theta) = -\frac{1}{m}\sum Cost(h_\theta(x), y) J(θ)=m1Cost(hθ(x),y)

上下两种形式都是等价的,可自行推导。


梯度下降求出权重矩阵:

​ 首先编写出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)

很快的得到权重矩阵:

image-20210705154012192

通过矩阵我们就可以绘制边界了:

绘制边界:
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()
lg-reset-boundary
预测与正确率:
def predict(theta, x):
    return np.round(sigmoid(x.dot(theta)))
print('Train Accuracy: %f', np.mean(np.double(p == y)) * 100)

参考文档:

Python fminunc 的替代方法

全部代码:

逻辑回归修正

部分代码参考:

Ace大佬的py版本

ning/blob/wrong/Logistic%20Regression/Logistic%20Regression-reset.py)

部分代码参考:

Ace大佬的py版本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值