线性回归模型
二元函数线性回归
多元函数线性回归
梯度下降公式
注意:如果多个变量的话要最后统一赋值(左边对右边错)
代码
void C拟合直线View::OnLinearRegression()
{
// TODO: 在此添加命令处理程序代码
st0 = 0; st1 = 0;//初始化seita
float af = 0.00001;//设置学习率
float st0_old = st0+1, st1_old = st1+1;
double V_sum_sum = 0, V_sum_sum_old = 20000000;
double V_sum_0 = 0, V_sum_1 = 0;
while (fabs(st0_old - st0)>0.0001||fabs(st1_old - st1)>0.0001)//判断条件 st0 st1变化不超过一个数
// while (fabs(V_sum_sum_old - V_sum_sum)>100)
{
V_sum_0 = 0;
V_sum_1 = 0;
V_sum_sum = 0;
V_sum_sum_old = V_sum_sum;
for (int i = 0; i < count; i++)
{
V_sum_0 += st0 + st1*mPoint[i].x - mPoint[i].y;
V_sum_1 += (st0 + st1*mPoint[i].x - mPoint[i].y)*mPoint[i].x;
V_sum_sum += (st0 + st1*mPoint[i].x - mPoint[i].y)*(st0 + st1*mPoint[i].x - mPoint[i].y);
}
st0_old = st0 ; st1_old = st1;
st0 = st0 - af*100*V_sum_0 / count;
st1 = st1 - af*V_sum_1 / count;
}
b = st0;//a,b是输出直线的两个参数y=a*x+b
a = st1;
}
运行结果
正规方程
核心是求出令代价函数每个偏导为0的参数
公式:
正规方程与梯度下降法的优缺点
梯度下降法 | 正规方程 |
---|---|
需要选择学习率α | 不需要选择学习率α |
需要多次迭代 | 不需要多次迭代,一次就能计算出来 |
特征量很多的时候也能运行很好 (十万个特征量) | 特征量很多时(XTX)-1 计算量过多(计算时间是特征量的3次方)十万级别为大概分界 |
matlab程序
p=[1,3;2,5;3,9;30,10;60,30;80,47;50,18]%输入点
n=3 %拟合的线公式最高次数 y=st(1)+st(2)*x^1+st(3)*x^2+...+st(n+1)*x^n
x= []
y=[]
for ii=1:size(p,1)
xx=[1]
for iii=1:n-1
xx=[xx,p(ii,1).^iii]
end
x=[x;xx]
y=[y;p(ii,2)]
end
%{
x=[
1,p(1,1),p(1,1).^2,p(1,1).^3;
1,p(2,1),p(2,1).^2,p(2,1).^3;
1,p(3,1),p(3,1).^2,p(3,1).^3;
1,p(4,1),p(4,1).^2,p(4,1).^3;
]
y=[p(1,2);p(2,2);p(3,2);p(4,2);]
%}
st=(((x')*x)^-1)*(x')*y %正规方程公式
i=[0:100]
j=[0]
for iii=1:n
j=j+st(iii).*(i.^(iii-1))
end
%j=st(1)+st(2).*i+st(3).*(i.^2)%+st(4).*(i.^3)
plot(p(:,1),p(:,2),'o')
hold on
plot(i,j)
结果
逻辑回归
本质是将线性回归的结果通过logistic函数转换到0-1之间,同时,logistic函数还能使得代价函数成为一个凸函数,从而可以使用梯度下降公式,寻找最低点
代价函数与cost
Cost函数
简化后的代价函数
一对多分类时
matlab代码
其中添加了学习率的pd控制并限幅,有一定的效果
pt_1=[1,1;3,3;2,4;4,5;7,-1;4,9;6,4]%输入正点
pt_0=[1,4;6,8;7,8;9,5;0,-1;6,-3;8,-2;9,0;4,11]%输入负点
plot(pt_0(:,1),pt_0(:,2),'or',pt_1(:,1),pt_1(:,2),'+b')%画出点
hold on
%分别计算正负点的个数
n_1=size(pt_1,1)
n_0=size(pt_0,1)
%分别为正点和负点的矩阵后面添加1的标志
pt_1=[pt_1 ,ones(n_1,1)]
pt_0=[pt_0 ,zeros(n_0,1)]
%将所有点放到一个矩阵中,并计算所有点的个数
pt=[pt_1;pt_0]
m=size(pt,1)
n=8 %设置要拟合的曲线公式的最高次数 a+b*x+c*y+d*x^2+e*x*y+f*y^2 此时,n为2
%定义xy矩阵,存放所有特征变量值和标定的结果
x=[]
y=[]
% 计算xy矩阵
% 格式 x为:
% [ 1 , 1 , 1 , 1 ,...1 ;
% x1 , x2 , x3 , x4 ,...,xm;
% y1 , y2 , y3 , y4 ,...,ym;
% x1^2 , x2^2 , x3^2 , x4^2 ,...,ym^2;
% x1*y1...
% y1^2...
% .
% .
% y1^n... ]
%
% y为:
% [ y1,y2,y3...ym ]
for ii=1:m
xx=[]
for j=0:n
for iii=0:j
xx=[xx;(pt(ii,1).^iii).*(pt(ii,2).^(j-iii))]
end
end
% xx=[1;pt(ii,1);pt(ii,2);pt(ii,1).^2;pt(ii,1).*pt(ii,2);pt(ii,2).^2;pt(ii,1).^3;(pt(ii,1).^2).*pt(ii,2);pt(ii,1).*(pt(ii,2).^2);pt(ii,2).^3]
x=[x,xx]
y=[y,pt(ii,3)]
end
%定义学习率 af=[0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01];
af_1=ones((n+2)*(n+1)/2,1)*0.0001
af=af_1
%初始化特征值st=[0;0;0;0;0;0;0;0;0;0;0;0;0;0;0];
st=ones((n+2)*(n+1)/2,1)*0
st_old=st+1%上一个特征值,为了判断梯度下降结束条件和引入学习率pd控制需要
sum=[0]%公式中间变量
s_1=-ones(1,n_1)%存储所有正点在当前特征值st下的值,为了判断是否分类成功用
s_0=ones(1,n_0)%同上
%while(max(s_0(:))>-4|min(s_1(:))<4|max(st_old-st)>0.00001|max(st-st_old)>0.00001)%分类成功且st变化小于某个数
while(max(s_0(:))>-1000|min(s_1(:))<1000)%是否分类成功
%while(max(st_old-st)>0.00001|max(st-st_old)>0.00001)%st变化小于某个数
st_old=st;
for ii=1:46600%每次迭代计算多次
%梯度下降公式,
sum=((1+ exp(-st'*x)).^(-1)-y)*x'/m;
st=st-sum'.*af;
end
%计算正负点带入当前特征值st后的结果,如果一个所有值大于0,一个所有值小于0,则分类成功
s_1=[ones(1,n_1)];%;pt_1(:,1)';pt_1(:,2)';(pt_1(:,1)').^2;(pt_1(:,1)').*(pt_1(:,2)');(pt_1(:,2)').^2;(pt_1(:,1)').^3;(pt_1(:,1)').^2.*(pt_1(:,2)');(pt_1(:,1)').*(pt_1(:,2)').^2;(pt_1(:,2)').^3];
s_0=[ones(1,n_0)];%;pt_0(:,1)';pt_0(:,2)';(pt_0(:,1)').^2;(pt_0(:,1)').*(pt_0(:,2)');(pt_0(:,2)').^2;(pt_0(:,1)').^3;(pt_0(:,1)').^2.*(pt_0(:,2)');(pt_0(:,1)').*(pt_0(:,2)').^2;(pt_0(:,2)').^3];
for j=1:n
for iii=0:j
s_1=[s_1;(pt_1(:,1)'.^iii).*(pt_1(:,2)'.^(j-iii))];
s_0=[s_0;(pt_0(:,1)'.^iii).*(pt_0(:,2)'.^(j-iii))];
end
end
s_1=st'*s_1
s_0=st'*s_0
st
af=af_1+abs(st-st_old)*0.04;%引入学习率af的pd控制
af=af.*(af<af_1*5)+2*af_1.*(af>=af_1*5);%学习率af限幅,大于af初始值的多少倍的话就是给这个值
end
%ellipsefig1(st(4),st(6),st(5),st(2),st(3),st(1));
%绘制图像,本来是二元多次函数的曲线图像,但是没找到合适的函数,
%通过采用绘制二元多次函数在一点范围内的三维图,设置z轴范围比如-1到1之间显示,从俯视图可以勉强看到曲线的形状
[x, y] = meshgrid(-10:0.05:20); % 步长可以适当地增大,
a=2
z=st(1)
for j=1:n
for iii=0:j
z=z+ st(a)*(x.^(iii)).*(y.^(j-iii));
a=a+1
end
end
%z = 3*x.^2+3*y.^2+3*x.*y+1-3*x-3*y;
%mesh(x, y, z)
surf(x, y, z)%显示三维图像
axis([-10 20 -10 20 -0.001 0.001])%限制z轴
view([-0.1,89.9])%设置观察角度,稍微倾斜一下曲线比较清晰
图像
线性回归的正则化
目的是解决过拟合问题,通过减少特征个数或者令某些特征量非常小,
通过下图方法可以使得指定特征值变的非常小
代价函数如下
梯度函数如下
正则化的正规方程如下
代码
p=[1,3;11,9;25,9;39,10;50,20;60,37;70,40;80,57]%;90,60]%输入点
n=7 %拟合的线公式最高次数 y=st(1)+st(2)*x^1+st(3)*x^2+...+st(n+1)*x^n
x= []
y=[]
for ii=1:size(p,1)
xx=[1];
for iii=1:n-1
xx=[xx,p(ii,1).^iii];
end
x=[x;xx];
y=[y;p(ii,2)];
end
%{
x=[
1,p(1,1),p(1,1).^2,p(1,1).^3;
1,p(2,1),p(2,1).^2,p(2,1).^3;
1,p(3,1),p(3,1).^2,p(3,1).^3;
1,p(4,1),p(4,1).^2,p(4,1).^3;
]
y=[p(1,2);p(2,2);p(3,2);p(4,2);]
%}
lbd=1000000;%正则化的系数
e=eye(n,n);%计算单位矩阵
e(1,1)=0;
st=(((x')*x)^-1)*(x')*y %正规方程公式
st_z=(((x')*x+lbd*e)^-1)*(x')*y %正则化后的正规方程公式
i=[0:100];
j=[0];
for iii=1:n
j=j+st(iii).*(i.^(iii-1));
end
%j=st(1)+st(2).*i+st(3).*(i.^2)%+st(4).*(i.^3)
plot(p(:,1),p(:,2),'ok')
hold on
plot(i,j,'r')
i=[0:100];
j=[0];
for iii=1:n
j=j+st_z(iii).*(i.^(iii-1));
end
plot(i,j,'b')
axis([0,100,0,100])
运行结果对比
红色未正则化,蓝色正则化
逻辑回归的正则化
代价函数
梯度下降函数
程序
pt_1=[1,1;3,3;2,4;4,6;7,1;4,0;7,2]%输入正点
pt_0=[1,7;6,8;7,8;9,5;0,-1;6,-3;8,-2;9,0;4,11]%输入负点
plot(pt_0(:,1),pt_0(:,2),'or',pt_1(:,1),pt_1(:,2),'+b')%画出点
hold on
%分别计算正负点的个数
n_1=size(pt_1,1)
n_0=size(pt_0,1)
%分别为正点和负点的矩阵后面添加1的标志
pt_1=[pt_1 ,ones(n_1,1)]
pt_0=[pt_0 ,zeros(n_0,1)]
%将所有点放到一个矩阵中,并计算所有点的个数
pt=[pt_1;pt_0]
m=size(pt,1)
n=6 %设置要拟合的曲线公式的最高次数 a+b*x+c*y+d*x^2+e*x*y+f*y^2 此时,n为2
%定义xy矩阵,存放所有特征变量值和标定的结果
x=[]
y=[]
% 计算xy矩阵
% 格式 x为:
% [ 1 , 1 , 1 , 1 ,...1 ;
% x1 , x2 , x3 , x4 ,...,xm;
% y1 , y2 , y3 , y4 ,...,ym;
% x1^2 , x2^2 , x3^2 , x4^2 ,...,ym^2;
% x1*y1...
% y1^2...
% .
% .
% y1^n... ]
%
% y为:
% [ y1,y2,y3...ym ]
for ii=1:m
xx=[]
for j=0:n
for iii=0:j
xx=[xx;(pt(ii,1).^iii).*(pt(ii,2).^(j-iii))]
end
end
% xx=[1;pt(ii,1);pt(ii,2);pt(ii,1).^2;pt(ii,1).*pt(ii,2);pt(ii,2).^2;pt(ii,1).^3;(pt(ii,1).^2).*pt(ii,2);pt(ii,1).*(pt(ii,2).^2);pt(ii,2).^3]
x=[x,xx]
y=[y,pt(ii,3)]
end
%定义学习率 af=[0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01;0.01];
af_1=ones((n+2)*(n+1)/2,1)*0.00003
af=af_1
%初始化特征值st=[0;0;0;0;0;0;0;0;0;0;0;0;0;0;0];
st=ones((n+2)*(n+1)/2,1)*0.0
st_old=st+1%上一个特征值,为了判断梯度下降结束条件和引入学习率pd控制需要
sum=[0]%公式中间变量
s_1=-ones(1,n_1)%存储所有正点在当前特征值st下的值,为了判断是否分类成功用
s_0=ones(1,n_0)%同上
e=ones((n+2)*(n+1)/2,1)
e(1:6,1)=0
lbd=15
%while(max(s_0(:))>-4|min(s_1(:))<4|max(st_old-st)>0.00001|max(st-st_old)>0.00001)%分类成功且st变化小于某个数
%while(max(s_0(:))>-0.1|min(s_1(:))<0.1)%是否分类成功
while(max(st_old-st)>0.001|max(st-st_old)>0.001)%st变化小于某个数
st_old=st;
for ii=1:46000%每次迭代计算多次
%梯度下降公式,
sum=((1+ exp(-st'*x)).^(-1)-y)*x'/m;
%st=st-sum'.*af;%未正则化
st=st.*(ones((n+2)*(n+1)/2,1)-lbd*e.*af)-sum'.*af;%正则化
end
%计算正负点带入当前特征值st后的结果,如果一个所有值大于0,一个所有值小于0,则分类成功
s_1=[ones(1,n_1)];%;pt_1(:,1)';pt_1(:,2)';(pt_1(:,1)').^2;(pt_1(:,1)').*(pt_1(:,2)');(pt_1(:,2)').^2;(pt_1(:,1)').^3;(pt_1(:,1)').^2.*(pt_1(:,2)');(pt_1(:,1)').*(pt_1(:,2)').^2;(pt_1(:,2)').^3];
s_0=[ones(1,n_0)];%;pt_0(:,1)';pt_0(:,2)';(pt_0(:,1)').^2;(pt_0(:,1)').*(pt_0(:,2)');(pt_0(:,2)').^2;(pt_0(:,1)').^3;(pt_0(:,1)').^2.*(pt_0(:,2)');(pt_0(:,1)').*(pt_0(:,2)').^2;(pt_0(:,2)').^3];
for j=1:n
for iii=0:j
s_1=[s_1;(pt_1(:,1)'.^iii).*(pt_1(:,2)'.^(j-iii))];
s_0=[s_0;(pt_0(:,1)'.^iii).*(pt_0(:,2)'.^(j-iii))];
end
end
s_1=st'*s_1
s_0=st'*s_0
st
af=af_1+abs(st-st_old)*0.1;%引入学习率af的pd控制
af=af.*(af<af_1*10)+2*af_1.*(af>=af_1*10);%学习率af限幅,大于af初始值的多少倍的话就是给这个值
end
%ellipsefig1(st(4),st(6),st(5),st(2),st(3),st(1));
%绘制图像,本来是二元多次函数的曲线图像,但是没找到合适的函数,
%通过采用绘制二元多次函数在一点范围内的三维图,设置z轴范围比如-1到1之间显示,从俯视图可以勉强看到曲线的形状
[x, y] = meshgrid(-10:0.05:20); % 步长可以适当地增大,
a=2
z=st(1)
for j=1:n
for iii=0:j
z=z+ st(a)*(x.^(iii)).*(y.^(j-iii));
a=a+1;
end
end
%z = 3*x.^2+3*y.^2+3*x.*y+1-3*x-3*y;
%mesh(x, y, z)
surf(x, y, z)%显示三维图像
axis([-10 20 -10 20 -0.001 0.001])%限制z轴
view([-0.1,89.9])%设置观察角度,稍微倾斜一下曲线比较清晰
结果对比
加了正则化后的图像
未加正则化