机器学习算法之Logistic Regression
文章目录
Logistic Regression
1.逻辑回归的介绍
逻辑回归算法是一种分类算法,是典型的监督学习,其训练样本包含样本的特征和标签信息,在二分类中,标签为离散值,如{+1,-1},分别表示正类和负类。分类算法通过对训练样本的学习,得到从样本特征到样本标签之间的映射关系,也被称为假设函数,之后可利用该假设函数对新数据进行分类。
2.逻辑回归模型
逻辑回归模型是广义线性模型的一种,属于线性的分类模型。对于图中的线性可分的问题,需要找到一条直线,能够将俩个不同的类分开。这条直线称为超平面,可以使用如下的线性函数表示
其中W为权重,b为偏置。多维情况下,W,b均为向量
3.阈值函数
为了将数据分成正负两个类别,可以使用阈值函数,将样本映射到不同类别中,常见的阈值函数有Sigmoid函数,其形式如下:
图像为:
对于输入向量X,其属于正例的概率为
属于负例的概率
4.损失函数
对于逻辑回归算法,其属于类别y的概率:
为了求参数W和b,可以使用极大似然法对其进行估计,其似然函数为:
其中
对于似然函数的极大值的求解,通常使用Log似然函数,在逻辑回归算法中,通常是将负的Log似然函数作为其损失函数,损失函数为:
此时,我们需要求min,可以使用基于梯度的方法求解
5.梯度下降法
在机器学习算法中,对于很多监督学习模型,需要对原始的模型构建损失函数l,接下来便是通过优化算法对损失函数l进行优化,以便寻找到最优的参数W。在求解机器学习参数W的优化算法时,使用较多的是基于梯度下降的优化算法(GD)。
梯度下降法的含义是通过当前点的梯度方向寻找到新的迭代点,并从当前点移动到新的迭代点继续寻找新的迭代点,直到找到最优解。该方法的优点:在求解过程中,只需求解损失函数的一阶导数,计算成本比较小。
梯度下降法的过程:
-
随机选择一个初始点
-
重复以下过程
- 决定梯度下降的方向:
- 选择步长
- 更新:
-
直到满足终止条件
6.梯度的求解
梯度为:
其中,表示的是样本的第j个分量。取 ,且将偏置项的变量设为1,则可将上述的梯度合并为:
根据梯度下降法,得到如下的更新公式:
7.步长的选择
对于步长的选择,若选择太小,会导致收敛速度比较慢;若选择太大,则会出现震荡的现象,即跳过最优解,在最优解附近徘徊
8.逻辑回归算法实践
利用训练样本训练逻辑回归模型
'''
Date:20190405
@author:codecat
'''
import numpy as np
import matplotlib.pyplot as plt
def load_data(file_name):
'''导入训练数据
input: file_name(string)训练数据的位置
output: feature_data(mat)特征
label_data(mat)标签
'''
f = open(file_name,'r') # 打开文件
feature_data = []
label_data = []
for line in f.readlines():
feature_tmp = []
lable_tmp = []
lines = line.strip().split("\t")
feature_tmp.append(1) # 偏置项
for i in range(len(lines) - 1):
feature_tmp.append(float(lines[i]))
lable_tmp.append(float(lines[-1]))
feature_data.append(feature_tmp)
label_data.append(lable_tmp)
f.close() # 关闭文件
return np.mat(feature_data), np.mat(label_data)
def sig(x):
'''Sigmoid函数
input: x(mat):feature * w
output: sigmoid(x)(mat):Sigmoid值
'''
return 1.0 / (1 + np.exp(-x))
def lr_train_bgd(feature, label, maxCycle, alpha):
'''利用梯度下降法训练LR模型
input: feature(mat)特征
label(mat)标签
maxCycle(int)最大迭代次数
alpha(float)学习率
output: w(mat):权重
'''
n = np.shape(feature)[1] # 特征个数
w = np.mat(np.ones((n, 1))) # 初始化权重
i = 0
while i <= maxCycle: # 在最大迭代次数的范围内
i += 1 # 当前的迭代次数
h = sig(feature * w) # 计算Sigmoid值
err = label - h
if i % 100 == 0:
print ("\t---------iter=" + str(i) + " , train error rate= " + str(error_rate(h, label)))
w = w + alpha * feature.T * err # 权重修正
return w
def error_rate(h, label):
'''计算当前的损失函数值
input: h(mat):预测值
label(mat):实际值
output: err/m(float):错误率
'''
m = np.shape(h)[0]
sum_err = 0.0
for i in range(m):
if h[i, 0] > 0 and (1 - h[i, 0]) > 0:
sum_err -= (label[i,0] * np.log(h[i,0]) + (1-label[i,0]) * np.log(1-h[i,0]))
else:
sum_err -= 0
return sum_err / m
def save_model(file_name, w):
'''保存最终的模型
input: file_name(string):模型保存的文件名
w(mat):LR模型的权重
'''
m = np.shape(w)[0]
f_w = open(file_name, "w")
w_array = []
for i in range(m):
w_array.append(str(w[i, 0]))
f_w.write("\t".join(w_array))
f_w.close()
def draw(weight,file_name):
x0List=[]
y0List=[]
x1List=[]
y1List=[]
f=open(file_name,'r')
for line in f.readlines():
lines=line.strip().split()
if lines[2]=='0':
x0List.append(float(lines[0]))
y0List.append(float(lines[1]))
else:
x1List.append(float(lines[0]))
y1List.append(float(lines[1]))
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x0List,y0List,s=10,c='red')
ax.scatter(x1List,y1List,s=10,c='green')
xList=[];yList=[]
x=np.arange(-3,13,0.1)
for i in range(len(x)):
xList.append(x[i])
y=(-weight[0]-weight[1]*x)/weight[2]
for j in range(y.shape[1]):
yList.append(y[0,j])
ax.plot(xList,yList)
plt.xlabel('x1');plt.ylabel('x2')
plt.show()
if __name__ == "__main__":
# 1、导入训练数据
print ("---------- 1.load data ------------")
feature, label = load_data("data.txt")
# 2、训练LR模型
print ("---------- 2.training ------------")
w = lr_train_bgd(feature, label, 1000, 0.01)
# 3、保存最终的模型
print ("---------- 3.save model ------------")
save_model("weights", w)
# 4,绘制图像
draw(w,'data.txt')
对新数据进行预测
'''
Date:20190405
@author:codecat
'''
import numpy as np
from lr_train import sig
def load_weight(w):
'''导入LR模型
input: w(string)权重所在的文件位置
output: np.mat(w)(mat)权重的矩阵
'''
f = open(w)
w = []
for line in f.readlines():
lines = line.strip().split("\t")
w_tmp = []
for x in lines:
w_tmp.append(float(x))
w.append(w_tmp)
f.close()
print(w)
return np.mat(w)
def load_data(file_name, n):
'''导入测试数据
input: file_name(string)测试集的位置
n(int)特征的个数
output: np.mat(feature_data)(mat)测试集的特征
'''
f = open(file_name)
feature_data = []
for line in f.readlines():
feature_tmp = []
lines = line.strip().split("\t")
if len(lines) != n - 1:
continue
feature_tmp.append(1)
for x in lines:
feature_tmp.append(float(x))
feature_data.append(feature_tmp)
f.close()
return np.mat(feature_data)
def predict(data, w):
'''对测试数据进行预测
input: data(mat)测试数据的特征
w(mat)模型的参数
output: h(mat)最终的预测结果
'''
h = sig(data * w.T)#sig
m = np.shape(h)[0]
for i in range(m):
if h[i, 0] < 0.5:
h[i, 0] = 0.0
else:
h[i, 0] = 1.0
return h
def save_result(file_name, result):
'''保存最终的预测结果
input: file_name(string):预测结果保存的文件名
result(mat):预测的结果
'''
m = np.shape(result)[0]
#输出预测结果到文件
tmp = []
for i in range(m):
tmp.append(str(result[i, 0]))
f_result = open(file_name, "w")
f_result.write("\n".join(tmp))
f_result.close()
if __name__ == "__main__":
# 1、导入LR模型
print ("---------- 1.load model ------------")
w = load_weight("weights")
n = np.shape(w)[1]
print(n)
# 2、导入测试数据
print ("---------- 2.load data ------------")
testData = load_data("test_data", n)
# 3、对测试数据进行预测
print ("---------- 3.get prediction ------------")
h = predict(testData, w)#进行预测
# 4、保存最终的预测结果
print ("---------- 4.save prediction ------------")
save_result("result", h)