线性回归(Linear Regression)

基本概念

线性回归( Linear Regression )是利用称为线性回归方程的最小平方函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析。这种函数是一个或多个称为回归系数的模型参数的线性组合。只有一个自变量的情况称为简单回归,大于一个自变量情况的叫做多元回归。

假设函数(Hypothesis function)

公式

代数表示

hθ(x)=θ0+θ1x1+...+θnxn

向量表示
hθ(x)=θτX

注: θ n+1 维的列向量 X (n+1)m维的向量。

代价函数(Cost function)

公式

结合平方误差和公式

J(θ)=1mΣmi=1(x(i)y(i))2

选择该公式的原因:

假设根据特征的预测结果与实际结果有误差 ϵ(i) ,那么预测结果 θτx(i) 与真实结果 y(i) 满足:

y(i)=θτx(i)+ϵ(i)

一般来讲,误差满足平均值为0的高斯分布,也就是正态分布。那么x和y的条件概率也就是:
p(y(i)|x(i);θ)=12πσexp((y(i)θτx(i))22σ2)

这样就估计了一条样本的结果概率,然而我们期待的是模型能够在全部样本上预测最准,也就是概率积最大。注意这里的概率积是概率密度函数积,连续函数的概率密度函数与离散值的概率函数不同。这个概率积成为最大似然估计。我们希望在最大似然估计得到最大值时确定θ。那么需要对最大似然估计公式求导,求导结果既是:
12Σmi=1(θτx(i)y(i))2

这就解释了为何误差函数要使用平方和。当然推导过程中也做了一些假定,但这个假定符合客观规律。

代数表示

J(θ)=12mΣmi=1(hθ(x(i))y(i))2

向量表示
J(θ)=12mθτXY

注: θ n+1 维的列向量, X (n+1)m维的向量, Y m+1维的列向量。

目标

通过训练找到使得 J(θ) 值最小的 θ .我们可以用梯度下降( gradient descent )法来求。

梯度下降法:

基本概念

梯度下降法,就是利用负梯度方向来决定每次迭代的新的搜索方向,使得每次迭代能使待优化的目标函数逐步减小。

在线性回归中的应用

每次对代价函数求偏导,得到前进的方向,然后设定一个学习的速率 α ,使得代价函数的值往小的方向收敛。
代数公式:

θi=θiαyJ(θ)

结合线性回归:
θj=θjαΣmi=1(hθ(x(i))y(i))x(i)j

注: α 的选择十分关键,过小需要的迭代次数较长,过大可能不会收敛,所有的 θ 需要同时更新(批量梯度下降)
向量表示:
θ=θαmX(XθY)

注:这样也保证了同时更新。
可以用线性代数的方法直接求出 θ
θ=(XτX)1XτY

matalb Code

Cost function

function J = computeCostMulti(X, y, theta)

m = length(y); % number of training examples

J = 0;

predictions = X*theta; %假设函数的值

sqrterror = (predictions-y).^2; %平方误差

J=1/(2*m)*sum(sqrterror);

end

gradient descent

function [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters)

m = length(y); % number of training examples
J_history = zeros(num_iters, 1);

for iter = 1:num_iters

    theta = theta - alpha/m*(X'*(X*theta-y));

    J_history(iter) = computeCostMulti(X, y, theta);

end

end

实例

链接

房价预测

Code

#include <bits/stdc++.h>

using namespace std;

typedef vector<double > vd;

struct data{
    vd x;
    double y;
    data(){
        x.clear();
        y=0;
    }
    data(const vd &_x,const double &_y){
        x=_x;
        y=_y;
    }
};

double H(vd x,vd thea)//hypothesis function
{
    int len = thea.size();
    double sum = 0;
    for(int i=0;i<len;i++)
        sum=sum+x[i]*thea[i];
    return sum;
}

double getvalue(data dt[],vd thea,int n){//最小二乘得到方差
    double sum = 0;
    for(int i=0;i<n;i++){
        double tmpsum = H(dt[i].x,thea);
        sum+=(tmpsum-dt[i].y)*(tmpsum-dt[i].y);
    }
    return sum/2.0;
}

void gradient(data dt[],vd &thea,int n,double alpha)//梯度下降更新thea
{
    int len = thea.size();
    vd tmp;
    for(int i=0;i<len;i++){
        double tmpsum = 0;
        for(int j=0;j<n;j++){
            tmpsum = tmpsum + alpha*(H(dt[j].x,thea)-dt[j].y)*dt[j].x[i];
        }
        tmp.push_back(thea[i]-tmpsum);
    }
    thea = tmp;
}

void solve(data dt[],vd &thea,int n)//处理迭代
{
    double alpha = 0.005;
    double delta = 1e-6;
    double pre = getvalue(dt,thea,n);
    double now = 0;
    while(abs(pre-now)>delta){
        pre = now;
        now = getvalue(dt,thea,n);
        gradient(dt,thea,n,alpha);
    }
}

int main()
{
    int f,t,m,n;
    while(~scanf("%d%d",&f,&n)){
        data test[110];
        for(int i=0;i<n;i++){
            vd tmp;
            double x;
            tmp.push_back(1.0);
            for(int i=0;i<f;i++){
                scanf("%lf",&x);
                tmp.push_back(x);
            }
            scanf("%lf",&x);
            test[i]=data(tmp,x);
        }
        scanf("%d",&m);
        data ans[110];
        for(int i=0;i<m;i++){
            vd tmp;
            double x;
            tmp.push_back(1.0);
            for(int i=0;i<f;i++){
                scanf("%lf",&x);
                tmp.push_back(x);
            }
            ans[i]=data(tmp,0);
        }
        vd thea;
        for(int i=0;i<=f;i++)
            thea.push_back(0);
        solve(test,thea,n);
        for(int i=0;i<m;i++){
            ans[i].y=H(ans[i].x,thea);
            printf("%.2lf\n",ans[i].y);
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值