依然是联系, 只不过是多变量的
但这次有点不一样, 因为你不得不normalization
结果是这个样子的
1.92077e+11 0.05
109139 -6719.28 340310
1.92102e+11 0.1
108828 -6864.04 340200
1.92144e+11 0.15
108512 -7010.52 340089
1.92206e+11 0.2
108192 -7159.55 339976
1.92286e+11 0.25
107869 -7310.78 339861
1.92386e+11 0.3
107541 -7464.25 339742
1.92507e+11 0.35
107210 -7619.77 339621
1.92649e+11 0.4
106876 -7777.23 339498
1.92812e+11 0.45
程序像这个样子
import std.stdio, std.math, std.conv, std.random, std.string;
class fit{
float a,b,c;
float alpha = 0.7;
float m;
float h(float x, float y){
return a*x+b*y+c;
}
void update(float x, float y, float z){
auto y1 = alpha*(h(x, y)-z)/m;
a -= y1*x;
b -= y1*y;
c -= y1;
}
this(float m){
a = uniform(-1.,1.);
b = uniform(-1.,1.);
c = uniform(-1.,1.);
this.m = m;
}
}
int main(){
float[][2] x;
float[] y;
float[2] mean = 0;
foreach(l;File("ex3x.dat").byLine){
int k=0;
foreach(s;split(l, " ")){
if (strip(s).length == 0) continue;
x[k] ~= to!float(strip(cast(string)s));
mean[k] += x[k][$-1];
k=(k+1)%2;
}
}
x[0][] -= mean[0] / x[0].length;
x[1][] -= mean[1] / x[1].length;
float[2] sig = 0;
foreach(i,arr;x) foreach(v;arr){
sig[i] += v^^2;
}
x[0][] /= sqrt(sig[0]/x[0].length);
x[1][] /= sqrt(sig[1]/x[1].length);
foreach(l;File("ex3y.dat").byLine){
y ~= to!float(strip(cast(string)l));
}
foreach(alpha;1..31){
auto f = new fit(y.length);
f.alpha = cast(float)alpha/20.;
foreach(k;0..1000){
foreach(i,v;y){
f.update(x[0][i], x[1][i], v);
}
}
float j=0;
foreach(i,v;y){
j += (f.h(x[0][i],x[1][i])-v)^^2;
}
writeln(j,"\t",f.alpha);
writeln(f.a,"\t",f.b,"\t",f.c);
delete f;
}
return 0;
}
没有内建的矩阵支持还是很痛苦的.
这种小程序我又不想导入gsl. 不过马上就会用到gsl了.
图明天画, 今天收工.
在我这里是0.2最好, 其实和迭代次数有关.