summaryrefslogtreecommitdiff
path: root/model
diff options
context:
space:
mode:
authorJoe Zhao <ztuowen@gmail.com>2015-04-11 17:46:19 +0800
committerJoe Zhao <ztuowen@gmail.com>2015-04-11 17:46:19 +0800
commit85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e (patch)
tree3059605ab0707b5530330dacdd9445b59bd73669 /model
parent5d57accc3e1bc2b89c1e7753f7dbb40f3c8f575a (diff)
downloadranksvm-85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e.tar.gz
ranksvm-85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e.tar.bz2
ranksvm-85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e.zip
completed & tested, train & predict
Diffstat (limited to 'model')
-rw-r--r--model/ranksvm.cpp4
-rw-r--r--model/ranksvm.h2
-rw-r--r--model/ranksvmtn.cpp117
-rw-r--r--model/ranksvmtn.h2
4 files changed, 62 insertions, 63 deletions
diff --git a/model/ranksvm.cpp b/model/ranksvm.cpp
index dc2ad9f..7ee72ac 100644
--- a/model/ranksvm.cpp
+++ b/model/ranksvm.cpp
@@ -40,8 +40,8 @@ RSVM* RSVM::loadModel(const string fname){
}
int RSVM::setModel(const SVMModel &model) {
- if (model.weight.cols()!=fsize)
- LOG(FATAL) << "Feature size mismatch: "<<fsize<<" "<<model.weight.cols();
+ if (model.weight.rows()!=fsize)
+ LOG(FATAL) << "Feature size mismatch: "<<fsize<<" "<<model.weight.rows();
this->model.weight=model.weight;
this->model.beta=model.beta;
return 0;
diff --git a/model/ranksvm.h b/model/ranksvm.h
index e82b6be..aa5e1ca 100644
--- a/model/ranksvm.h
+++ b/model/ranksvm.h
@@ -26,7 +26,7 @@ protected:
int fsize;
public:
virtual int train(DataList &D)=0;
- virtual int predict(DataList &D,std::list<double> &res)=0;
+ virtual int predict(DataList &D,std::vector<double> &res)=0;
// TODO Not sure how to construct this
// Possible solution: generate a nxn matrix each row contains the sorted list of ranker result.
int saveModel(const std::string fname);
diff --git a/model/ranksvmtn.cpp b/model/ranksvmtn.cpp
index 776d4db..959ea7d 100644
--- a/model/ranksvmtn.cpp
+++ b/model/ranksvmtn.cpp
@@ -7,7 +7,8 @@ using namespace std;
using namespace Eigen;
const int maxiter = 10;
-const double prec=1e-3;
+const double prec=1e-4;
+const double C=1;
int cg_solve(const MatrixXd &A, const VectorXd &b, VectorXd &x)
{
@@ -20,9 +21,7 @@ int cg_solve(const MatrixXd &A, const VectorXd &b, VectorXd &x)
{
// Non preconditioned version
r_1 = res.dot(res);
- cout<<step<<":"<<r_1<<endl;
- write_stream(cout,res);
- if (r_1<1e-5) // Terminate condition
+ if (r_1<1e-10) // Terminate condition
break;
if (step){
beta = r_1 / r_2;
@@ -33,9 +32,6 @@ int cg_solve(const MatrixXd &A, const VectorXd &b, VectorXd &x)
alpha = r_1/p.dot(q);
x=x+p*alpha;
res=res-q*alpha;
- write_stream(cout,p);
- write_stream(cout,q);
- cin.get();
++step;
r_2=r_1;
}
@@ -43,16 +39,12 @@ int cg_solve(const MatrixXd &A, const VectorXd &b, VectorXd &x)
}
// Calculate objfunc gradient & support vectors
-int objfunc_linear(const VectorXd &w,const MatrixXd &A,const double C,VectorXd &pred,VectorXd &grad, double &obj,MatrixXd &sv)
+int objfunc_linear(const VectorXd &w,const MatrixXd &D,const MatrixXd &A,const double C,VectorXd &pred,VectorXd &grad, double &obj)
{
- pred = pred.cwiseMax(MatrixXd::Zero(pred.rows(),pred.cols()));
+ for (int i=0;i<pred.rows();++i)
+ pred(i)=pred(i)>0?pred(i):0;
obj = (pred.cwiseProduct(pred)*C).sum()/2 + w.dot(w)/2;
- grad = w - (((pred*C).transpose()*A)*w).transpose();
- for (int i=0;i<pred.cols();++i)
- if (pred(i)>0)
- sv(i,i)=1;
- else
- sv(i,i)=0;
+ grad = w - (((pred*C).transpose()*A)*D).transpose();
return 0;
}
@@ -63,36 +55,40 @@ int line_search(const VectorXd &w,const MatrixXd &D,const MatrixXd &A,const Vect
double g,h;
t = 0;
VectorXd Xd=A*(D*step);
+ VectorXd pred2;
while (1)
{
- pred = pred - t*Xd;
+ pred2 = pred - t*Xd;
g=wd+t*dd;
h=dd;
- for (int i=0;i<pred.cols();++i)
- if (pred(i)>0) {
- g += pred(i)*Xd(i);
- h += Xd(i)*Xd(i);
+ for (int i=0;i<pred2.rows();++i)
+ if (pred2(i)>0) {
+ g -= C*pred2(i)*Xd(i);
+ h += C*Xd(i)*Xd(i);
}
+ g=g+1e-12;
+ h=h+1e-12;
+ t=t-g/h;
+ cout<<g<<":"<<h<<endl;
+ cin.get();
if (g*g/h<1e-10)
break;
}
+ pred=pred2;
return 0;
}
int train_orig(int fsize, MatrixXd &D,MatrixXd &A,VectorXd &weight){
int iter = 0;
- double C=1;
- long n=D.rows();
- LOG(INFO) << "training with feature size:" << fsize << " Data size:" << n;
- MatrixXd sv=MatrixXd::Identity(n, n);
+ long n=A.rows();
+ LOG(INFO) << "training with feature size:" << fsize << " Data size:" << n << " Relation size:" << A.rows();
VectorXd grad(fsize);
VectorXd step(fsize);
VectorXd pred(n);
double obj,t;
pred=VectorXd::Ones(n) - (A*(D*weight));
-
while (true)
{
iter+=1;
@@ -103,21 +99,28 @@ int train_orig(int fsize, MatrixXd &D,MatrixXd &A,VectorXd &weight){
}
// Generate support vector matrix sv & gradient
- objfunc_linear(weight,A,C,pred,grad,obj,sv);
+ objfunc_linear(weight,D,A,C,pred,grad,obj);
step = grad*0;
- MatrixXd H = MatrixXd::Identity(grad.cols(),grad.cols());
-
+ MatrixXd H = MatrixXd::Identity(grad.rows(),grad.rows());
// Compute Hessian directly
for (int i=0;i<n;++i)
- if (sv(i,i)>0)
- H = H + 2*C*A.row(i).transpose()*A.row(i);
+ if (pred(i)>0) {
+ VectorXd v = A.row(i)*D;
+ H = H + C * (v * v.transpose());
+ }
// Solve
+ //cout<<obj<<endl;
cg_solve(H,grad,step);
// do line search
line_search(weight,D,A,step,pred,t);
weight=weight+step*t;
+ int sv=0;
+ for (int i=0;i<n;++i)
+ if (pred(i)>0)
+ ++sv;
// When dec is small enough
- if (-step.dot(grad) < prec * obj)
+ LOG(INFO)<<"Iter: "<<iter<<" Obj: " <<obj<<" SV: "<< sv << " Newton decr:"<<step.dot(grad)/2 << " linesearch: "<< -t ;
+ if (step.dot(grad) < prec * obj)
break;
}
return 0;
@@ -125,55 +128,51 @@ int train_orig(int fsize, MatrixXd &D,MatrixXd &A,VectorXd &weight){
int RSVMTN::train(DataList &D){
MatrixXd Data(D.getSize(),D.getfSize()),A;
- int i=0,j=0;
- list<DataEntry*>::iterator iter,st,nx;
- for (iter= D.getData().begin();i<D.getSize();++i,++iter)
- for (j=0;j<D.getfSize();++j)
- Data(i,j)=(*iter)->feature(j);
- nx=st=iter= D.getData().begin();
- ++nx;
+ int i,j;
+ LOG(INFO)<<"Processing input";
+ for (i=0;i<D.getSize();++i) {
+ for (j = 0; j < D.getfSize(); ++j)
+ Data(i, j) = (D.getData()[i])->feature(j);
+ }
int cnt=0;
- while (iter!=D.getData().end())
+ i=j=0;
+ while (i<D.getSize())
{
- if ((nx == D.getData().end())||(*iter)->qid!=(*nx)->qid)
+ if ((i+1 == D.getSize())|| D.getData()[i]->qid!=D.getData()[i+1]->qid)
{
- list<DataEntry*>::iterator high,low=iter;
- for (high=st;((*high)->rank)>0;++high)
- for (low=iter;((*low)->rank)<0;--low)
- ++cnt;
- st = nx;
+ int high=j;
+ while (D.getData()[high]->rank>0)
+ ++high;
+ cnt += (high-j)*(i-high+1);
+ j = i+1;
}
- ++iter;
+ ++i;
}
A.resize(cnt,D.getSize());
- nx=st=iter= D.getData().begin();
- ++nx;
cnt=i=j=0;
- while (iter!=D.getData().end())
+ while (i<D.getSize())
{
- if ((nx == D.getData().end())||(*iter)->qid!=(*nx)->qid)
+ if ((i+1 == D.getSize())|| D.getData()[i]->qid!=D.getData()[i+1]->qid)
{
int v1=j,v2;
- list<DataEntry*>::iterator high,low=iter;
- for (high=st;((*high)->rank)>0;++high,++v1)
- for (low=iter,v2=i;((*low)->rank)<0;--low,--v2) {
+ for (v1=j;(D.getData()[v1]->rank)>0;++v1)
+ for (v2=i;(D.getData()[v2]->rank)<0;--v2) {
A(cnt,v1) = 1;
A(cnt,v2) = -1;
++cnt;
}
- st = nx;
- j=i+1;
+ j = i+1;
}
++i;
- ++iter;
}
train_orig(fsize,Data,A,model.weight);
return 0;
};
-int RSVMTN::predict(DataList &D, list<double> &res){
+int RSVMTN::predict(DataList &D, vector<double> &res){
//TODO define A
- for (list<DataEntry*>::iterator i=D.getData().begin(), end=D.getData().end();i!=end;++i)
- res.push_back(((*i)->feature).dot(model.weight));
+ res.clear();
+ for (int i=0;i<D.getSize();++i)
+ res.push_back(((D.getData()[i])->feature).dot(model.weight));
return 0;
}; \ No newline at end of file
diff --git a/model/ranksvmtn.h b/model/ranksvmtn.h
index 6ed6ad7..fd99d19 100644
--- a/model/ranksvmtn.h
+++ b/model/ranksvmtn.h
@@ -13,7 +13,7 @@ public:
return "TN";
};
virtual int train(DataList &D);
- virtual int predict(DataList &D,std::list<double> &res);
+ virtual int predict(DataList &D,std::vector<double> &res);
};
int cg_solve(const Eigen::MatrixXd &A, const Eigen::VectorXd &b, Eigen::VectorXd &x);