逻辑回归
逻辑回归和线性回归很像,差别在于逻辑回归在线性回归的基础上加了一个激活函数。逻辑回归所使用的激活函数也分两种,一个是sigmoid函数,一个是softmax函数,前者用于二分类,称为逻辑回归,后者用于多分类,一般称为逻辑分类。线性回归输出的y值通过sigmoid函数,会产生N1维的大小均在0和1之间的向量,也就是每个样本属于正样本的概率值,而y值通过softmax函数,会输出NC维的矩阵,C表示样本预测值可能的类别数。
为什么要在线性回归的基础上用这两个激活函数呢?我的理解是,其一,算是对y值进行了一个归一化,因为单纯的线性回归,如果不对x进行归一化,那么拟合出来的y值可能会差别很大,那么在分类问题上,你阈值取多少才合适呢?这个范围就很大了,而sigmoid函数和softmax函数能够把y值映射到[0,1]区间上,表示样本属于正样本的概率大小,这个问题就解决了。其二,这两个函数都具有近似阶跃函数的特性,也就是能够把样本区分得足够开,这样能够让分类的准确率更高些,否则y的线性回归预测值靠近0时,很容易错分。
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
data=[
[-0.017612,14.053064,0],
[-0.752157,6.538620,0],
[-1.322371,7.152853,0],
[0.423363,11.054677,0],
[0.569411,9.548755,0],
[-0.026632,10.427743,0],
[0.667394,12.741452,0],
[1.347183,13.175500,0],
[1.217916,9.597015,0],
[-0.733928,9.098687,0],
[1.416614,9.619232,0],
[1.388610,9.341997,0],
[0.317029,14.739025,0],
[-0.576525,11.778922,0],
[-1.781871,9.097953,0],
[-1.395634,4.662541,1],
[0.406704,7.067335,1],
[-2.460150,6.866805,1],
[0.850433,6.920334,1],
[1.176813,3.167020,1],
[-0.566606,5.749003,1],
[0.931635,1.589505,1],
[-0.024205,6.151823,1],
[-0.036453,2.690988,1],
[-0.196949,0.444165,1],
[1.014459,5.754399,1],
[1.985298,3.230619,1],
[-1.693453,-0.557540,1],
[-0.346811,-1.678730,1],
[-2.124484,2.672471,1]
]
data=np.array(data)
# 绘制数据
# plt.scatter(data[:,0],data[:,1],color='blue',marker='o',label='POsitive')
# plt.show()
# 对变量做归一化
data[:,:2]=data[:,:2]/np.max(np.abs(data[:,:2]),axis=0)
x=np.mat(data.copy())[:,0:-1]
y=np.mat(data.copy())[:,-1]
# print(y)
#添加偏置
x=np.mat(np.hstack((np.ones((x.shape[0],1)),x)))
# print(x)
# 初始化权重
w=np.random.randn(x.shape[-1],1)
minLoss=0.1
stepLen=0.02
maxTurn=3000
turn=0
y_predict=np.dot(x,w)
# print(y_predict)
#通过同时 1/1+e(-x)预测概率
y_predict=1/(1+np.exp(-y_predict))
# 计算损失函数
loss=0
loss = np.sum(y.reshape(1,-1) * np.log2(y_predict) + (1 - y.reshape(1,-1)) * np.log2(1-y_predict))
loss=-loss/y.shape[0]
print("loss:",loss)
while (abs(loss)>minLoss and turn<maxTurn):
w = w - stepLen * np.dot(x.T, y_predict - y)
y_predict = np.dot(x, w)
# print(y_predict)
# 通过同时 1/1+e(-x)预测概率
y_predict = 1 / (1 + np.exp(-y_predict))
# 计算损失函数
loss = 0
loss = np.sum(y.reshape(1, -1) * np.log2(y_predict) + (1 - y.reshape(1, -1)) * np.log2(1 - y_predict))
loss = -loss / y.shape[0]
print("loss:", loss)
turn+=1
print('===============')
print(y_predict)
w=np.squeeze(np.array(w))
print("w:",w)
#迭代完毕之后画出曲线
# 直线第一个坐标(x1,y1)
x1 = -2
y1 = -1 / w[2] * (w[0] * 1 + w[1] * x1)
# 直线第二个坐标(x2,y2)
x2 = 2
y2 = -1 / w[2] * (w[0] * 1 + w[1] * x2)
# 作图
# print(x)
plt.scatter(np.array(x)[:,1],np.array(x)[:,2],color='blue',marker='o',label='POsitive')
plt.plot([x1,x2], [y1,y2],'r')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend(loc = 'upper left')
plt.show()