基于神经网络的二分类模型代码解析:结构、算法与训练过程
程序的设计思路是基于神经网络的二分类模型。主要包括一个'Network'类和一些辅助函数。
'Network'类中包含了训练次数(epoches)和学习率(learning_rate)作为超参数,并初始化了权重(w1, w2, w3, w4, w5, w6)和参数(b1, b2, b3)。在构造函数中对这些参数进行初始化。
'Network'类中定义了激活函数'sigmoid'和激活函数的导数'deriv_sigmoid'。'sigmoid'函数将输入的值压缩到0和1之间,而'deriv_sigmoid'函数则是'sigmoid'函数的导数。
'Network'类中的'forward'函数实现了前向传播的计算过程。它接收一个数据向量作为输入,通过一系列的线性变换和激活函数得到最终的输出值。
'Network'类中的'train'函数用于训练模型。它接收训练数据和标签作为输入,并通过反向传播算法更新神经网络的参数。在每个训练周期内,遍历所有的训练样本,计算预测值和损失,并根据损失和梯度下降算法更新参数。同时,每隔一定的训练周期,输出当前训练次数和损失值。
'Network'类中的'predict'函数用于预测模型的输出。它接收测试数据和标签作为输入,通过前向传播得到预测值,并与标签进行对比,计算正确率。
在'main'函数中,定义了训练数据和标签,创建了一个'Network'对象,并调用'train'函数进行训练。然后定义了测试数据和标签,调用'predict'函数进行预测。
整个程序的目的是训练一个二分类模型,通过训练数据学习到合适的参数和权重,并在测试数据上进行预测,计算预测的正确率。
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
//获取误差:
double getMSEloss(double x1, double x2)
{
return (x1 - x2) * (x1 - x2);
}
class Network{
private:
int epoches;//训练次数。
double learning_rate;//学习率。
double w1, w2, w3, w4, w5, w6;//权重。
double b1, b2, b3;//参数。
public:
// 超参数、参数初始化:
Network(int es, double lr) :epoches(es), learning_rate(lr)
{
w1 = w2 = w3 = w4 = w5 = w6 = 0;
b1 = b2 = b3 = 0;
}
// 激活函数:
double sigmoid(double x)
{
return 1 / (1 + exp(-x));
}
// 激活函数求导:
double deriv_sigmoid(double x)
{
double y = sigmoid(x);
return y * (1 - y);
}
// 前向传播:
double forward(vector<double> data)
{
double sum_h1 = w1 * data[0] + w2 * data[1] + b1;
double h1 = sigmoid(sum_h1);
double sum_h2 = w3 * data[0] + w4 * data[1] + b2;
double h2 = sigmoid(sum_h2);
double sum_o1 = w5 * h1 + w6 * h2 + b3;
return sigmoid(sum_o1);
}
//训练数据数组:
void train(vector<vector<double>> data, vector<double> label)
{
for (int epoch = 0; epoch < epoches; ++epoch)
{
int total_n = data.size();
for (int i = 0; i < total_n; ++i)
{
vector<double> x = data[i];
double sum_h1 = w1 * x[0] + w2 * x[1] + b1;
double h1 = sigmoid(sum_h1);
double sum_h2 = w3 * x[0] + w4 * x[1] + b2;
double h2 = sigmoid(sum_h2);
double sum_o1 = w5 * h1 + w6 * h2 + b3;
double o1 = sigmoid(sum_o1);
double pred = o1;
//反向算法更新神经网络参数:
double d_loss_pred = -2 * (label[i] - pred);
double d_pred_w5 = h1 * deriv_sigmoid(sum_o1);
double d_pred_w6 = h2 * deriv_sigmoid(sum_o1);
double d_pred_b3 = deriv_sigmoid(sum_o1);
double d_pred_h1 = w5 * deriv_sigmoid(sum_o1);
double d_pred_h2 = w6 * deriv_sigmoid(sum_o1);
double d_h1_w1 = x[0] * deriv_sigmoid(sum_h1);
double d_h1_w2 = x[1] * deriv_sigmoid(sum_h1);
double d_h1_b1 = deriv_sigmoid(sum_h1);
double d_h2_w3 = x[0] * deriv_sigmoid(sum_h2);
double d_h2_w4 = x[1] * deriv_sigmoid(sum_h2);
double d_h2_b2 = deriv_sigmoid(sum_h2);
w1 -= learning_rate * d_loss_pred * d_pred_h1 * d_h1_w1;
w2 -= learning_rate * d_loss_pred * d_pred_h1 * d_h1_w2;
b1 -= learning_rate * d_loss_pred * d_pred_h1 * d_h1_b1;
w3 -= learning_rate * d_loss_pred * d_pred_h2 * d_h2_w3;
w4 -= learning_rate * d_loss_pred * d_pred_h2 * d_h2_w4;
b2 -= learning_rate * d_loss_pred * d_pred_h2 * d_h2_b2;
w5 -= learning_rate * d_loss_pred * d_pred_w5;
w6 -= learning_rate * d_loss_pred * d_pred_w6;
b3 -= learning_rate * d_loss_pred * d_pred_b3;
}
if (epoch % 10 == 0)
{
double loss = 0;
for (int i = 0; i < total_n; ++i)
{
double pred = forward(data[i]);
loss += getMSEloss(pred, label[i]);
}
//输出训练次数与误差:
cout << 'Epoch:' << epoch << ' Loss: ' << loss << endl;
}
}
}
//预测数据数组:
void predict(vector<vector<double>> testdata, vector<double> testlabel)
{
int n = testdata.size();
double temp = 0;
for (int i = 0; i < n; ++i)
{
double pred = forward(testdata[i]);
pred = pred > 0.5 ? 1 : 0;
temp += (testlabel[i] == pred);
}
//输出判断的正确率:
cout << '正确率:' << temp / n *100<<'%' << endl;
}
};
int main()
{
//训练:
vector<vector<double>> data = { {1,2},{3,4},{5,6},{-7,-8} };
vector<double> label = { 0,0,0,1 };
Network network = Network(2000, 0.1);
network.train(data, label);
//得出预测结论:
vector<vector<double>> testdata = { {8,7},{-5,-6},{-2,-5},{6,8},{-5,-1} };
vector<double> testlabel = { 0,1,1,0,1 };
network.predict(testdata, testlabel);
return 0;
}
原文地址: https://www.cveoy.top/t/topic/qwJg 著作权归作者所有。请勿转载和采集!