提问者:小点点

编辑线性回归代码以接收两个向量


我有一个线性回归算法,我想编辑,所以它需要两个向量。这两个向量是从csv文件中的数据创建的,我想使用线性回归来比较这两个向量中的数据,并基于它们进行预测。下面的算法只接受一个包含要比较的两个值的向量,但我想改变它,使它可以接受两个独立的向量,并比较两个向量之间的值。或者像算法那样把我的两个向量组合成单个向量会更容易吗?

#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;

// Some data
istringstream str( "1  3\n"
                   "2  5\n"
                   "3  7\n"
                   "4  9\n"
                   "5 11\n" );


//======================================================================


struct Data{ double x, y; };


//======================================================================


vector<Data> getData( istream &in )
{
   vector<Data> result;
   for ( double x, y; in >> x >> y; ) result.push_back( { x, y } );
   return result;
}


//======================================================================


void regression( const vector<Data> &data, double &m, double &c )
{
   int N = data.size();
   double Sx = 0, Sy = 0, Sxx = 0, Sxy = 0, Syy = 0;
   for ( Data d : data )
   {
      double x = d.x, y = d.y;
      Sx += x;
      Sy += y;
      Sxx += x * x;
      Sxy += x * y;
      Syy += y * y;
   }
   m = ( N * Sxy - Sx * Sy ) / ( N * Sxx - Sx * Sx );  // slope
   c = ( Sy - m * Sx ) / N;                            // intercept
}


//======================================================================


void training( const vector<Data> &data, double &m, double &c, double alpha, int passes )
{
   m = c = 0.0;
   while( passes-- )
   {
      for ( Data d : data )
      {
         double error = m * d.x + c - d.y;
         c -= alpha * error;
         m -= alpha * error * d.x;
      }
   }
}


//======================================================================


void write( const vector<Data> &data, double m, double c )
{
   #define fmt << setw( 20 ) <<
   cout << "Regression line is y = " << m << "x + " << c << "\n\n";
   cout << fixed << setprecision( 6 );
   cout << "For comparison (x, y, ypred):\n";
   for ( Data d : data ) cout fmt d.x fmt d.y fmt m * d.x + c << '\n';
}


//======================================================================


int main()
{
   double m, c;                        // slope and intercept; y = mx+c
   vector<Data> data = getData( str );

   cout << "Read " << data.size() << " points\n\n";


   // STANDARD METHOD
   cout << "Regression (STANDARD METHOD)\n";
   regression( data, m, c );
   write( data, m, c );


   // GRADIENT-DESCENT METHOID
   int passes = 5;
   double alpha = 0.1;
   cout << "\n\nRegression (GRADIENT DESCENT)\n";
   training( data, m, c, alpha, passes );
   write( data, m, c );
}

共1个答案

匿名用户

该算法确实与同时具有xy的结构一起工作。最简单的方法是以这样的结构复制单独的向量:

std::vector<Data> transform(const std::vector<double>& x, const std::vector<double>& y) {
     std::vector<Data> result(x.size());
     for (int i=0; i < x.size(); ++i) {
          result[i] = { x[i], y[i] };
     }
     return result;
}

这是相当昂贵的,因为它复制了所有的数据。也许您可以更改生成xy的代码,使其生成一个std::vector。如果要修改算法,只需替换任何出现的std::vector;带有两个独立std::vectorv;x,y以及每个v[i].xx[i]

PS该算法的实际问题在于它是在容器上工作,而不是在迭代器上工作。如果算法将使用迭代器,那么在不同类型的容器中使用它会更简单,而不需要复制数据或修改算法。