对于回归问题,最小二乘可以说是黄金油。首先说正规方程,笔者本科学的是测绘,测绘的核心是确定点在空间坐标系中的位置,对于外业测量的数据难免会存在误差,如何消除粗差,获得最优值,笔者经历了《测量平差》这门课程。而机器学习的正规方程可以对应测量平差的法方程。
如 y=a*x+b 问题,按照平差知识,观测值+观测值改正数=近似值+近似值改正数,即
测量平差的核心就是:min[PVV],即改正数的加权平方和最小。
故可以将一元线性回归写成如下误差方程:
法方程为:
正规方程的优点是无需迭代、但是当你的数据量很大的时候,程序就会很吃力。所以我们要采取它的替代品—梯度下降
梯度下降的原理很简单,
编程的时候,对于matlab 或者python一定要利用其向量化优势,这样可以避免循环。
对于逻辑回归的假设:
对于非线性肯定首先要线性化,然后迭代需要初值。笔者程序以LR为类,当然逻辑回归不等于回归,一个损失函数是平方,一个是对数,而且逻辑回归属于分类。
对于欠拟合和过拟合问题:
对于欠拟合:
1、 增加特征数目
2、 使用复杂模型
对于过拟合
1、 增加训练集
2、 正则化
3、 降维
笔者下面代码是LR回归的正则化,仔细看的话,将其写成法方程形式,无非就是给法方程系数主对角线增加了一个系数,相当于岭回归,加上惩罚函数。
LR代码:
import numpy as np
import matplotlib.pyplot as plt
def sigmiod(x):
return 1/(1+np.exp(-x))
def gradient_decreasing(traindata,trainlabel):
# traindata 第一列数据为1
m,n=traindata.shape
alpha=0.01
thelta=np.ones((n,1))
num=200
for i in range(num):
thelta1=thelta
h=sigmiod(traindata*thelta)
error=h-trainlabel
thelta=thelta-alpha*traindata.T*error*(1/len(traindata))
return thelta
#计算训练集分类误差
def error_train(thelta):
# traindata=np.matrix(traindata)
h=sigmiod(traindata*thelta)
label=np.ones((traindata.shape[0],1))
count=0
for i in range(traindata.shape[0]):
if h[i,0]>=0.5:
label[i,0]=1
else:
label[i,0]=0
if label[i,0]!=trainlabel[i,0]:
count+=1
print("error_rate:%g"%(count/traindata.shape[0]))
#预测测试集
def test_data(testdata,thelta):
testdata=np.matrix(testdata)
h=sigmiod(testdata*thelta)
label=np.zeros((len(testdata),1))
for i in range(len(h)):
if h[i,0]>=0.5:
label[i,0]= 1
else:
label[i,0] =0
return label
''' 当特征数目为2时,可以画图'''
def plotdecision_boundary(thelta):
x1,y1,x2,y2=[],[],[],[]
for i in range(len(traindata)):
if trainlabel[i]==1:
x1.append(traindata[i,1])
y1.append(traindata[i,2])
else:
x2.append(traindata[i,1])
y2.append(traindata[i,2])
x=np.arange(-3,3,0.01)
y=(-thelta[0,0]-thelta[1,0]*x)/thelta[2,0]
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(x1,y1,'r+',label="label=1")
ax.plot(x2,y2,'g+',label="label=0")
plt.legend(loc='best')
ax.plot(x,y,'r-')
if __name__=='__main__':
traindata=[]
trainlabel=[]
with open(r'C:\Users\Y\Desktop\python 3程序\traindata.csv','r') as file:
for line in file.readlines():
feature =line.strip().split(',')
traindata.append([1.0]+feature[0:-1])#数据第一列为1,连接列表
trainlabel.append([feature[-1]])#最后一列,标签值
traindata=np.matrix(traindata,np.float)
trainlabel=np.matrix(trainlabel,np.float)
thelta=gradient_decreasing(traindata,trainlabel)
error_train(thelta)
plotdecision_boundary(thelta)
label=test_data([[1,0.45,8.23],[1,0.3,100]],thelta)
正则化代码:
```
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
def sigmiod(x):
return 1/(1+np.exp(-x))
def gradient_decreasing_Regu(traindata,trainlabel):
m,n=traindata.shape
alpha=0.01
thelta=np.matrix(np.ones((n,1)))
iter_numer=200
lampda=10#正则化参数,lampda,过大的话造成除了thelta0,其它都为0,欠拟合,一条直线
loss=[]
for i in range(iter_numer):
h=sigmiod(traindata*thelta)
error=h-trainlabel
#正则化时候i,thelta 0 和其它值变化如下两行代码,区别之处
thelta[0,0]=thelta[0,0]-alpha*traindata[:,0].T*error*(1/m)
thelta[1:,0]=thelta[1:,0]*(1-alpha*lampda/m)-alpha*traindata[:,1:].T*error*(1/m)
loss.append((np.sum(np.array(error)*np.array(error)[0]))/(2*len(traindata)))
return thelta,loss
def plotdecision_boundary(thelta):
x1,y1,x2,y2=[],[],[],[]
for i in range(len(traindata)):
if trainlabel[i]==1:
x1.append(traindata[i,1])
y1.append(traindata[i,2])
else:
x2.append(traindata[i,1])
y2.append(traindata[i,2])
x=np.arange(-3,3,0.01)
y=(-thelta[0,0]-thelta[1,0]*x)/thelta[2,0]
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(x1,y1,'r+',label="label=1")
ax.plot(x2,y2,'g+',label="label=0")
plt.legend(loc='best')
ax.plot(x,y,'r-')
plt.title("LR正则化",fontproperties='FangSong',fontsize=14)
plt.text(x[-1],y[-1],"y=%s*x+%s"%(-thelta[1,0]/thelta[2,0],-thelta[0,0]/thelta[2,0]),fontproperties='FangSong',fontsize=14)
if __name__=='__main__':
traindata=[]
trainlabel=[]
with open(r'C:\Users\Y\Desktop\python 3程序\traindata.csv','r') as file:
for line in file.readlines():
feature =line.strip().split(',')
traindata.append([1.0]+feature[0:-1])
trainlabel.append([feature[-1]])
traindata=np.matrix(traindata,np.float)
trainlabel=np.matrix(trainlabel,np.float)
thelta,loss=gradient_decreasing_Regu(traindata,trainlabel)
plotdecision_boundary(thelta)
x1=np.arange(1,201)
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(x1,loss,'r-')
plt.xlabel("N-parameters updata")
plt.ylabel("loss")
迭代次数与代价函数的关系图
,
当正则化系数很大的时候,它就会近似一条直线,lampda=1000时候如下图: