我刚开始学习C++,我认为一个好的入门方法是构建我在其他语言中已经构建过的基本模型。我想从使用一阶方法解决的线性回归开始。所以,这里是我想要的组织方式(伪代码)。
class LinearRegression LinearRegression: tol = <提供的容差或默认值为1e-5> max_ite = <提供的最大迭代次数或默认值为1k> fit(X, y): // 模型针对此数据集学习权重 _gradient(X, y): // 计算梯度 score(X,y): // 模型使用从fit中学到的权重来计算 // y_predicted与实际y的准确性
我的问题是,当我使用fit、score和gradient方法时,我实际上不需要传递数组(X和y),甚至不需要在任何地方存储它们,所以我想使用对这些结构的引用或指针。我的问题是,如果方法接受指向二维数组的指针,我需要提前提供第二个维度的大小,或者使用模板。如果我使用模板,现在每个接受二维数组的方法看起来像这样
template<std::size_t rows, std::size_t cols> void fit(double (&X)[rows][cols], double &y){...}
这似乎不太好。我希望我的回归类能够处理任何大小的输入。行业中是如何做的?我知道在某些情况下,数组只是被展平成行或列主格式,只传递到第一个元素的指针,但我没有足够的经验来知道人们在C++中使用什么。
回答:
你在问题中提到了很多点,所以这里是针对这些点的几点说明:
-
现代C++不鼓励直接处理需要手动分配或释放的堆分配数据。你可以使用,例如,
std::vector<double>
来表示向量,使用std::vector<std::vector<double>>
来表示矩阵。更好的选择是使用一个矩阵类,最好是一个已经广泛使用的矩阵类。 -
一旦你使用这样的类,你就可以在运行时轻松获取维度。例如,使用
std::vector
,你可以使用size()
方法。其他类有其他方法。查看你选择的类的文档。 -
你可能真的不想为维度使用模板。
a. 如果你这样做,每次输入不同时,你都需要重新编译。你的代码将被编译器复制到你同时使用的不同维度的数量。很多不好的事情发生,而收益很少(在这种情况下)。从类中在运行时获取维度没有任何真正的缺点。
b. 在你的设置中,模板适合矩阵的类型(例如,它是
double
的矩阵还是float
的矩阵),或者可能适合维度数量(例如,用于指定张量)。 -
你的回归器不需要存储矩阵和/或向量。通过
const
引用传递它们。你的接口看起来像sklearn
的。如果你喜欢,可以查看那里的源代码。调用fit
的结果只是导致类对象存储与预测向量β对应的参数。它不复制或存储输入矩阵和/或向量。