diff options
| author | Joe Zhao <ztuowen@gmail.com> | 2015-04-11 17:46:19 +0800 | 
|---|---|---|
| committer | Joe Zhao <ztuowen@gmail.com> | 2015-04-11 17:46:19 +0800 | 
| commit | 85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e (patch) | |
| tree | 3059605ab0707b5530330dacdd9445b59bd73669 /model | |
| parent | 5d57accc3e1bc2b89c1e7753f7dbb40f3c8f575a (diff) | |
| download | ranksvm-85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e.tar.gz ranksvm-85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e.tar.bz2 ranksvm-85a4962556b67d1cc0668ecb2fbb03b3b4dd6e7e.zip  | |
completed & tested, train & predict
Diffstat (limited to 'model')
| -rw-r--r-- | model/ranksvm.cpp | 4 | ||||
| -rw-r--r-- | model/ranksvm.h | 2 | ||||
| -rw-r--r-- | model/ranksvmtn.cpp | 117 | ||||
| -rw-r--r-- | model/ranksvmtn.h | 2 | 
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);  | 
