В чем разница между реализацией градиентного спуска из учебника и реализацией тензорных потоков?
Либо я делаю ошибку при градиентном спуске, либо тензорный поток что-то делает кроме реализации учебника. Я не могу понять, какой именно.
Я написал код на C++, реализующий простейший пример ИНС. Линейная активация, 1 скрытый слой, 10 узлов. Вот мой код на C++:
class Layer
{
public:
double threshold = 0.5;
VectorXd zl;
MatrixXd Weights;
void create_layer(int n_nodes, const Layer &ConnectedLayer)
{
Weights = normrnd(0, sqrt(1.0 / (ConnectedLayer.zl.size() + n_nodes)), n_nodes,
ConnectedLayer.zl.size());
zl.resize(n_nodes);
}
void create_input_layer(int n_nodes)
{
zl.resize(n_nodes);
}
template
void compute_self(Layer &ConnectedLayer, const T &ActivationClass)
{
zl = ActivationClass.activation(Weights, ConnectedLayer.zl);
}
void compute_self(VectorXd &x)
{
zl = x;
}
};
class Network
{
public:
vector layers;
double learning_rate;
double Fx_diff_tol;
double abs_err_tol;
int sims;
int batch_size;
map X_batches;
map y_batches;
bool permute;
Network(int _sims, int _batch_size, double _learning_rate, double _Fx_diff_tol, double _abs_err_tol,
bool _permute = true)
{
sims = _sims;
batch_size = _batch_size;
learning_rate = _learning_rate;
Fx_diff_tol = _Fx_diff_tol;
abs_err_tol = _abs_err_tol;
permute = _permute;
}
void add_layer(Layer L)
{
layers.push_back(L);
}
template
VectorXd compute_net(const MatrixXd &X, const T &ActivationClass)
{
VectorXd z_output(X.rows());
for (int i = 0; i < X.rows(); ++i)
{
for (int k = 0; k < layers.size(); ++k)
{
if (k == 0)
{
VectorXd z0 = X.row(i);
layers[0].compute_self(z0);
}
else
{
layers[k].compute_self(layers[k - 1], ActivationClass);
}
}
z_output(i) = layers[layers.size() - 1].zl.value();
}
return z_output;
}
void check_gradient(MatrixXd &grad)
{
double clip = 100;
for (int i = 0; i < grad.rows(); i++)
{
for (int j = 0; j < grad.rows(); j++)
{
if (abs(grad(i, j)) < 1e-6)
{
grad(i, j) = 0;
}
}
}
if (grad.squaredNorm() > clip)
{
grad = clip * grad / grad.squaredNorm();
}
}
void check_gradient(VectorXd &grad)
{
double clip = 100;
for (int i = 0; i < grad.rows(); i++)
{
if (abs(grad(i)) < 1e-6)
{
grad(i) = 0;
}
}
if (grad.squaredNorm() > clip)
{
grad = clip * grad / grad.squaredNorm();
}
}
void batch_data(const MatrixXd &X, const VectorXd &y, bool permute = true)
{
time_t now = time(0);
boost::random::mt19937 GLOBAL_SEED(now);
std::mt19937 eng(GLOBAL_SEED);
if (permute)
{
PermutationMatrix perm(X.rows());
perm.setIdentity();
shuffle(perm.indices().data(), perm.indices().data() + perm.indices().size(), eng);
MatrixXd Xcopy = perm * X;
VectorXd ycopy = perm * y;
int rows = Xcopy.rows();
int batches = rows / batch_size;
int rem = rows % batch_size;
if (rem)
{
batches++;
}
int c = 0;
for (int b = 0; b < batches; ++b)
{
if (c + batch_size - 1 < rows)
{
X_batches = Xcopy.block(c, 0, batch_size, Xcopy.cols());
y_batches = ycopy.segment(c, batch_size);
c += batch_size;
}
else
{
X_batches = Xcopy.block(c, 0, rem, Xcopy.cols());
y_batches = ycopy.segment(c, rem);
c += batch_size;
}
}
}
else
{
int rows = X.rows();
int batches = rows / batch_size;
int rem = rows % batch_size;
if (rem)
{
batches++;
}
int c = 0;
for (int b = 0; b < batches; ++b)
{
if (c + batch_size - 1 < rows)
{
X_batches = X.block(c, 0, batch_size, X.cols());
y_batches = y.segment(c, batch_size);
c += batch_size;
}
else
{
X_batches = X.block(c, 0, rem, X.cols());
y_batches = y.segment(c, rem);
c += batch_size;
}
}
}
}
template
VectorXd run_model(const MatrixXd &X, const VectorXd &targets, const T1 &ActivationObj, const T2 &Loss)
{
double delta = learning_rate;
VectorXd grad_z_E;
MatrixXd grad_w_E;
double avg_error = 0;
double error;
batch_data(X, targets, permute);
int Batches = y_batches.size();
map deltas;
for (int i = 1; i
Подробнее здесь: https://stackoverflow.com/questions/784 ... nt-descent
Невозможно воспроизвести мини-пакетный градиентный спуск Tensorflow [закрыто] ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение