模型实现代码,关键是train函数和predict函数,都很容易。
#include <iostream>
#include <string>
#include <math.h>
#include "LogisticRegression.h"
using namespace std;
LogisticRegression::LogisticRegression(
int size, // N
int in, // n_in
int out // n_out
)
{
N = size;
n_in = in;
n_out = out;
// initialize W, b
// W[n_out][n_in], b[n_out]
W = new double*[n_out];
for(int i=0; i<n_out; i++)
W[i] = new double[n_in];
b = new double[n_out];
for(int i=0; i<n_out; i++)
{
for(int j=0; j<n_in; j++)
{
W[i][j] = 0;
}
b[i] = 0;
}
}
LogisticRegression::~LogisticRegression()
{
for(int i=0; i<n_out; i++)
delete[] W[i];
delete[] W;
delete[] b;
}
void LogisticRegression::train (
int *x, // the input from input nodes in training set
int *y, // the output from output nodes in training set
double lr // the learning rate
)
{
// the probability of P(y|x)
double *p_y_given_x = new double[n_out];
// the tmp variable which is not necessary being an array
double *dy = new double[n_out];
// step 1: calculate the output of softmax given input
for(int i=0; i<n_out; i++)
{
// initialize
p_y_given_x[i] = 0;
for(int j=0; j<n_in; j++)
{
// the weight of networks
p_y_given_x[i] += W[i][j] * x[j];
}
// the bias
p_y_given_x[i] += b[i];
}
// the softmax value
softmax(p_y_given_x);
// step 2: update the weight of networks
// w_new = w_old + learningRate * differential (导数)
// = w_old + learningRate * x (1{y_i=y} - p_yi_given_x)
// = w_old + learningRate * x * (y - p_y_given_x)
for(int i=0; i<n_out; i++)
{
dy[i] = y[i] - p_y_given_x[i];
for(int j=0; j<n_in; j++)
{
W[i][j] += lr * dy[i] * x[j] / N;
}
b[i] += lr * dy[i] / N;
}
delete[] p_y_given_x;
delete[] dy;
}
void LogisticRegression::softmax (double *x)
{
double max = 0.0;
double sum = 0.0;
// step1: get the max in the X vector
for(int i=0; i<n_out; i++)
if(max < x[i])
max = x[i];
// step 2: normalization and softmax
// normalize -- 'x[i]-max', it's not necessary in traditional LR.
// I wonder why it appears here?
for(int i=0; i<n_out; i++)
{
x[i] = exp(x[i] - max);
sum += x[i];
}
for(int i=0; i<n_out; i++)
x[i] /= sum;
}
void LogisticRegression::predict(
int *x, // the input from input nodes in testing set
double *y // the calculated softmax probability
)
{
// get the softmax output value given the current networks
for(int i=0; i<n_out; i++)
{
y[i] = 0;
for(int j=0; j<n_in; j++)
{
y[i] += W[i][j] * x[j];
}
y[i] += b[i];
}
softmax(y);
}