基本概念
線性迴歸(
假設函數(Hypothesis function)
公式
代數表示
向量表示
注:
代價函數(Cost function)
公式
結合平方誤差和公式
選擇該公式的原因:
假設根據特徵的預測結果與實際結果有誤差
ϵ(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
這就解釋了爲何誤差函數要使用平方和。當然推導過程中也做了一些假定,但這個假定符合客觀規律。
代數表示
向量表示
注:
目標
通過訓練找到使得
梯度下降法:
基本概念
梯度下降法,就是利用負梯度方向來決定每次迭代的新的搜索方向,使得每次迭代能使待優化的目標函數逐步減小。
在線性迴歸中的應用
每次對代價函數求偏導,得到前進的方向,然後設定一個學習的速率
代數公式:
結合線性迴歸:
注:
向量表示:
注:這樣也保證了同時更新。
可以用線性代數的方法直接求出
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;
}