线性回归
线性回归是最简单的机器学习模型之一,但是它也包含了机器学习中最基本的思想,个人觉得它的实现思路与神经网络等深度学习从原理上并没有太大的区别。对于回归问题:
y
=
w
T
x
+
b
y=w^Tx + b
y=wTx+b
利用梯度下降原理对
w
w
w,
b
b
b进行更新:
w
t
+
1
=
w
t
−
α
∗
1
/
m
∗
∑
i
=
1
n
(
y
i
p
−
y
i
r
)
w^{t+1}=w^t - \alpha*1/m*\sum_{i=1}^{n}{(y^p_i-y^r_i)}
wt+1=wt−α∗1/m∗∑i=1n(yip−yir)
b
t
+
1
=
b
t
−
α
∗
1
/
m
∗
∑
i
=
1
n
(
(
y
i
p
−
y
i
r
)
∗
x
i
)
b^{t+1}=b^{t}-\alpha*1/m*\sum_{i=1}^{n}{((y^p_i-y^r_i)*x_i})
bt+1=bt−α∗1/m∗∑i=1n((yip−yir)∗xi)
主函数:
#include <iostream>
#include "LinearRegression.h"
#include<fstream>
using namespace std;
double* readFile(string fileName) {
ifstream in;
in.open(fileName);
double temp;
int index = 0;
double* data = new double[50];
while (in >> temp) {
data[index] = temp;
index++;
}
for (int i = 0; i < 50; i++)
cout << "X,Y" << data[i] << endl;
return data;
}
int main() {
double alpha = 0.07;
int iterations = 200;
double x_predict = 2.1212;
double y_predict;
// 读取文件
string fileNameX = "ex2x.dat";
string fileNameY = "ex2y.dat";
ifstream in;
in.open(fileNameX);
double temp;
int length = 0;
while (in >> temp) {
length++;
}
double* X = new double[length];
double* Y = new double[length];
// 模型训练预测
X = readFile(fileNameX);
Y = readFile(fileNameY);
LinearRegression lr(X, Y, length);
lr.train(alpha, iterations);
y_predict = lr.predict(x_predict);
cout << y_predict << endl;
system("pause");
return 0;
}
/*******************************************************************
*《周志华 机器学习》C++代码
*
* htfeng
* 2018.09.28
*
* 第三章:线性模型
* 主要写线性回归
*******************************************************************/
#include <iostream>
#include <fstream>
#include "LinearRegression.h"
#include "Utils.h"
using namespace std;
//初始化
LinearRegression::LinearRegression(double x[], double y[], int m)
{
this->x = x;
this->y = y;
this->m = m;
}
//梯度下降
double *LinearRegression::gradient_descent(double x[], double y[], double alpha, int iters, double *J, int m)
{
double *theta = new double[2];
theta[0] = 1;
theta[1] = 1;
for (int i = 0; i < iters; i++)
{
double *predictions = calculate_predictions(x, theta, m);
double *diff = Utils::array_diff(predictions, y, m);
double *error_x1 = diff;
double *error_x2 = Utils::array_multiplication(diff, x, m);
theta[0] = theta[0] - alpha * (1.0 / m) * Utils::array_sum(error_x1, m);
theta[1] = theta[1] - alpha * (1.0 / m) * Utils::array_sum(error_x2, m);
J[i] = compute_cost(x, y, theta, m);
}
return theta;
}
// 训练函数
void LinearRegression::train(double alpha, int iterations) {
double *J = new double[iterations];//将J定义为一个包含了iterations个元素的数组
this->theta = gradient_descent(x, y, alpha, iterations, J, m); //m表示训练集的个数
cout << "J = ";
for (int i = 0; i < iterations; ++i) {
cout << J[i] << " ";
}
cout << endl << "Theta: " << theta[0] << " " << theta[1] << endl;
}
//预测
double LinearRegression::predict(double x) {
return h(x, theta);
}
//计算误差
double LinearRegression::compute_cost(double x[], double y[], double theta[], int m) {
double *predictions = calculate_predictions(x, theta, m);
double *diff = Utils::array_diff(predictions, y, m);
double *sq_errors = Utils::array_pow(diff, m, 2);
return (1.0 / (2 * m)) * Utils::array_sum(sq_errors, m);
}
//预测单个值
double LinearRegression::h(double x, double theta[]) {
return theta[0] + theta[1] * x;
}
//预测
double *LinearRegression::calculate_predictions(double x[], double theta[], int m) {
double * predictions = new double[m];
for (int i = 0; i < m; i++) {
predictions[i] = h(x[i], theta);
}
return predictions;
}
#ifndef ML_LINEARREGRESSION_H//如果这个宏没有被定义
#define ML_LINEARREGRESSION_H//则定义宏
class LinearRegression {
public:
double *x;
double *y;
int m;
double *theta;
__declspec(dllexport) LinearRegression(double x[], double y[], int m);
__declspec(dllexport) void train(double alpha, int iterations);
__declspec(dllexport) double predict(double x);
private:
//计算模型损失
__declspec(dllexport) static double compute_cost(double x[], double y[], double theta[], int m);
//计算单个预测值
__declspec(dllexport) static double h(double x, double theta[]);
//预测
__declspec(dllexport) static double *calculate_predictions(double x[], double theta[], int m);
//梯度下降
__declspec(dllexport) static double *gradient_descent(double x[], double y[], double alpha, int iter, double *J, int m);
};
#endif
#ifndef __UTILS__
#define __UTILS__
#include<string>
#include<iostream>
using namespace std;
class Utils {
public:
static double* array_diff(double predictions[], double y[], int m);
static double* array_multiplication(double diff[], double x[], int m);
static double* array_pow(double error[], int m, int n);
static double array_sum(double error[], int m);
};
double* Utils::array_diff(double predictions[], double y[], int m) {
double *diff = new double[m];
for (int i = 0; i < m; i++) {
diff[i] = predictions[i] - y[i];
}
return diff;
}
double* Utils::array_multiplication(double diff[], double x[], int m) {
double *differror = new double[m];
for (int i = 0; i < m; i++) {
differror[i] = diff[i] * x[i];
}
return differror;
}
double Utils::array_sum(double error[], int m) {
double sum = 0.0;
for (int i = 0; i < m; i++)
{
sum += error[i];
}
return sum;
}
double* Utils::array_pow(double error[], int m, int n)
{
double *sq_errors = new double[m];
for (int i = 0; i < m; i++)
{
sq_errors[i] = pow(error[i], n);
}
return sq_errors;
}
#endif
参考:https://github.com/fenghaotong/MachineLearningInCPlusPlus