转载至https://zhuanlan.zhihu.com/p/80969579
一 线性回归
线性回归,顾名思义是利用线性模型对数据点进行拟合的,常见的广义线性模型如下:
将上面的广义向量模型用向量的形式表示出来如下:
其中为向量。
最简单也是最常见的线性回归是最小二乘法
1.最小二乘法
最小二乘法是以均方误差为回归任务的性能度量,衡量预测值 f(x) 和真实值 y 之间的差值。优化问题就可以用下式表示出来:
从字面上理解最小二乘法就是试图找到一条直线,使所有样本到直线上的欧几里得距离之和最小。
这里有两个参数需要我们求解 和 ,其中为标量称为偏置, 为向量,其维数对应数据的维数(即大数据中的特征个数)。求解这两个参数的方法是对其求偏导。
令上式等于0得到w和b的最优解。
代码实现:
(1)matlab代码
一般的这类问题的求解思路就是找出损失函数,这里我们考虑一般的情况,一般情况下的损失函数为:
再求出梯度(即一阶偏导),对于大多数问题是不能直接求出最大小值的,所以一般会用梯度下降法来求解,设置学习率 进行更新。
权重的梯度:
偏置 b 的梯度:
得到了权重w和偏置b的梯度就可以用梯度下降法来求出合适的w和b了。更新公式如下:
一般初始化w和b全为1,
matlab代码如下:
%随机生成数据clear all
x(:,1)=rand(100,1);
x(:,2)=x(:,1);
[n,~]=size(x);
r=randn(n,1);
for i=1:n
y(i)=3x(i,1)+4x(i,2)+5+r(i);
end
y=y’;
plot3(x(:,1),x(:,2),y,”b“)
grid on
function [w,b]=line_regress(x,y)
[m,n]=size(x);
w=zeros(n,1);
b=1;
alpha=0.07;
MAX_DD=1500;
for i=1:MAX_DD
h=xw;
w=w-alpha(1/m)x’(h+b-y);
b=b-alpha(b+sum(h-y)/m);
end
(2)python—mxnet库的常规实现
from mxnet import ndimport mxnet.autograd as agfrom IPython import displayimport matplotlib.pyplot as pltimport random#定义样本和特征数量num_sample=1000num_feature=2weight=[2,-3.4]b_true=4.3#生成随机数据feature=nd.random.normal(scale=1,shape=(num_sample,num_feature))label=weight[0]*feature[:,0]+weight[1]*feature[:,1]+b_truelabel+=nd.random.normal(scale=0.01,shape=label.shape)def svg_fig(): # display.set_matplotlib_formats('svg') display.display_svg()def setfig_size(figsize=(3.5,2.5)): svg_fig() plt.rcParams["figure.figsize"]=figsizesetfig_size()plt.scatter(feature[:,1].asnumpy(),label.asnumpy(),1)#plt.show()w=nd.random.normal(scale=0.01,shape=(num_feature,1))b=nd.zeros(shape=(1,))w.attach_grad()b.attach_grad()def Linreg(x,w,b): return nd.dot(x,w)+bdef squared_loss(y_hat, y): # 本函数已保存在d2lzh包中方便以后使用 return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2def sgd(params, lr, batch_size): # 本函数已保存在d2lzh包中方便以后使用 for param in params: param[:] = param - lr * param.grad / batch_sizealpha=0.03epochs=1000for i in range(epochs): with ag.record(): l=squared_loss(Linreg(feature,w,b),label) l.backward() sgd([w,b],alpha,num_sample)print(w,b)
(3)python —mxnet库的简单实现
from mxnet import ndimport mxnet.autograd as agfrom IPython import displayimport matplotlib.pyplot as pltimport random#定义样本和特征数量num_inputs = 2num_feature = 1000true_w = [2, -3.4]true_b = 4.2feature = nd.random.normal(scale=1, shape=(num_feature, num_inputs))label = true_w[0] * feature[:, 0] + true_w[1] * feature[:, 1] + true_blabel += nd.random.normal(scale=0.01, shape=label.shape)#线性回归简洁实现#1.数据处理from mxnet.gluon import data as gdatadata=gdata.ArrayDataset(feature,label)#2.定义模型from mxnet.gluon import nnnet=nn.Sequential()net.add(nn.Dense(1))from mxnet import initnet.initialize(init.Normal(sigma=0.01))#3.定义损失函数from mxnet.gluon import loss as glossloss=gloss.L2Loss()#4.定义训练器from mxnet import gluontrainer=gluon.Trainer(net.collect_params(),'sgd',{'learning_rate':0.03})epchos=1000for i in range(epchos): with ag.record(): l=loss(net(feature),label) l.backward() trainer.step(num_feature)dense=net[0]w=dense.weight.data()b=dense.bias.data()print(w,b)
二 多项式拟合
前面的线性回归是一种多元回归问题,每个样本对应于多个特征,在前面的例子中,特征之前的值相差不大,所以没有做特征缩放,实际上严格的执行是需要特征缩放的因为有些特征值之间的量纲不同差距很大,如吴恩达的机器学习系类视频中 的例子,假设房屋的价格和房屋的面积及房屋的卧室数量有关,但是这两个特征之间值相差很大,这个时候直接用上面的线性回归时,将出现问题,所以必须进行特征缩放,一般特征缩放有两种计算方式。
(1)Z-score normalization,量化后的特征将服从标准正态分布:
(2)Min-Max Scaling,特征量化:
在大部分的机器学习中用的比较多的时第一种量化方法。
多项式拟合是一种典型的需要特征缩放的例子,一般解决的是一元多项式的数据拟合问题,形如:
多项式拟合也可以看成一种多元线性拟合,将其看为有n个特征的多元线性拟合, x 为一个特征, -为一个特征……。
当 时, , 。
对其进行缩放后利用线性拟合一样的方法就能求出拟合曲线,matlab代码如下:
function [w]=ploy_regression()
num_input=1;
num_ploy=3;
num_feature=100;
x=randn(100,1);
x=sort(x);
y=sin(x);
w=randn(num_ploy,num_input);
b=0;
X=ones(num_feature,num_ploy);
for i=1:num_ploy if i==1
X(:,i)=x;
else
X(:,i)=X(:,i-1).*x;
end
end
for i=1:num_ploy%
maxnum=max(X(:,i));%
minnum=min(X(:,i));
meannum=mean(X(:,i));
X(:,i)=(X(:,i)-meannum)/(std(X(:,i)));
end
epochs=1000;
alpha=0.01;
lamda=0.1;
for i=1:epochs H=X*w+b;
dw=X'*(H-y)*(1/num_feature)+(1/num_feature)*lamda*w;
db=sum(H-y)*(1/num_feature);
w=w-alpha*dw;
b=b-alpha*db;
end
y1=X*w+b;
p=polyfit(x,y,3);
y2=polyval(p,x);
plot(x,y,"r*",x,y1,"b-",x,y2,"g-")
end