我在他的在线书《 NeuralNetworksAndDeepLearning》中基于Michael Nielsen的Python代码构建了一个神经网络。我使用JavaScript,而不是Numpy,而是使用Tensorflow.js。网络正在运行,但是我想找到一种方法来减轻训练后的负担和偏见。我只想将Tensorflow用于矩阵/矢量运算,因为我想遵循Nielsen的书并学习神经网络的工作原理。我相信Layers API提供了一种保存模型的方法,但是我试图不依赖Layers来做到这一点。谢谢你的帮助。
export class Network {
constructor(sizes) {
this.num_layers = sizes.length;
this.sizes = sizes;
this.biases = [];
for (let i = 1; i < sizes.length; i++) {
this.biases.push(tf.randomNormal([sizes[i], 1]));
}
this.weights = [];
for (let j = 0; j < sizes.length - 1; j++) {
this.weights.push(tf.randomNormal([sizes[j + 1], sizes[j]]));
}
}
shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
feedforward(act) {
let a = act;
for (let i = 0; i < this.num_layers - 1; i++) {
a = tf.tidy(() => tf.sigmoid(this.weights[i].dot(a).add(this.biases[i])));
}
return a;
}
SGD(training_data, epochs, mini_batch_size, eta, test_data = null) {
let n_test;
let n = training_data.length;
if (test_data) n_test = test_data.length;
for (let j = 0; j < epochs; j++) {
this.shuffleArray(training_data);
let mini_batches = [];
for (let k = 0; k < n; k += mini_batch_size) {
mini_batches.push(training_data.slice(k, k + mini_batch_size));
}
mini_batches.forEach(mb => {
[this.weights, this.biases] = tf.tidy(() =>
this.update_mini_batch([...mb], eta)
);
});
if (test_data) {
console.log(`Epoch ${j}: ${this.evaluate(test_data)} / ${n_test}`);
} else {
console.log(`Epoch ${j} complete`);
}
console.log("Epoch complete:");
console.log("Weights:");
this.weights.forEach(x => x.print());
console.log("Biases:");
this.biases.forEach(x => x.print());
}
}
update_mini_batch(mini_batch, eta) {
//console.log(tf.memory().numTensors);
let nabla_b = [];
let nabla_w = [];
for (let i = 0; i < this.num_layers - 1; i++) {
nabla_b.push(tf.zeros(this.biases[i].shape));
nabla_w.push(tf.zeros(this.weights[i].shape));
}
let x, y;
mini_batch.forEach(data => {
x = data[0];
y = data[1];
let delta_nabla_b, delta_nabla_w;
[delta_nabla_b, delta_nabla_w] = this.backprop(x, y);
nabla_b = nabla_b.map((nb, i) => {
return nb.add(delta_nabla_b[i]);
});
nabla_w = nabla_w.map((nw, i) => {
return nw.add(delta_nabla_w[i]);
});
});
let weights = this.weights.map((w, i) => {
return w.sub(tf.mul(nabla_w[i], eta / mini_batch.length));
});
let biases = this.biases.map((b, i) => {
return b.sub(tf.mul(nabla_b[i], eta / mini_batch.length));
});
this.weights.forEach((x, i) => {
x.dispose();
this.biases[i].dispose();
});
return [weights, biases];
}
backprop(x, y) {
let nabla_b = [];
let nabla_w = [];
for (let i = 0; i < this.num_layers - 1; i++) {
nabla_b.push(tf.zeros(this.biases[i].shape));
nabla_w.push(tf.zeros(this.weights[i].shape));
}
let activation = x;
let activations = [x];
let zs = [];
this.biases.forEach((b, i) => {
let z = this.weights[i].dot(activation).add(b);
zs.push(z);
activation = z.sigmoid();
activations.push(activation);
});
let delta = this.cost_derivative(
activations[activations.length - 1],
y
).mul(this.sigmoid_prime(zs[zs.length - 1]));
nabla_b[nabla_b.length - 1] = delta;
nabla_w[nabla_w.length - 1] = delta.dot(
activations[activations.length - 2].transpose()
);
for (let i = this.num_layers - 2; i > 0; i--) {
let z = zs[i - 1];
let sp = this.sigmoid_prime(z);
delta = this.weights[i]
.transpose()
.dot(delta)
.mul(sp);
nabla_b[i - 1] = delta;
nabla_w[i - 1] = delta.dot(activations[i - 1].transpose());
//sp.dispose();
}
return [nabla_b, nabla_w];
}
evaluate(test_data) {
let sum = 0;
test_data.forEach(data => {
let x = tf.tidy(() => this.feedforward(data[0]).argMax());
let y = data[1].argMax();
let xvalue = x.dataSync()[0];
let yvalue = y.dataSync()[0];
if (xvalue === yvalue) {
sum++;
}
x.dispose();
});
return sum;
}
cost_derivative(output_activations, y) {
return output_activations.sub(y);
}
sigmoid_prime(z) {
return z.sigmoid().mul(tf.sub(1, z.sigmoid()));
}
}
答案 0 :(得分:1)
使用图层API,可以通过在图层上使用getWeights
来获得模型的权重。还有多种保存模型的方法:在localStorage中,在磁盘上,...
由于使用的是自己的网络实现,因此只需使用localStorage保存模型权重即可。
localStorage.setItem('weights', weights).
然后,在加载模型时,您可以检查是否已经存储了一些权重,然后进行了检索
答案 1 :(得分:1)
您可以使用tensor.array()
(或tensor.arraySync()
)函数来序列化任何张量。
代码示例
以下代码示例会将您的权重序列化为字符串。
const t = tf.tensor2d([[1,2], [3,4]]); // sample tensor
const dataArray = t.arraySync();
const serializedString = JSON.stringify(dataArray);
console.log(serializedString); // outputs: [[1,2],[3,4]]
您现在可以获取结果字符串并将其保存到磁盘(使用Node.js时),或通过localStorage将其存储在浏览器中(见下文)。
要反序列化数据,可以使用tf.tensor
函数:
const serializedString = '[[1,2],[3,4]]';
const dataArray = JSON.parse(serializedString);
const t = tf.tensor(dataArray);
t.print();
t
与上面的张量相同,代码的输出为:
Tensor
[[1, 2],
[3, 4]]
使用localStorage
要将序列化的字符串保存到localStorage并检索它,可以使用以下代码:
localStorage.setItem('myTensor', serializedString); // save tensor
const serializedString = localStorage.getItem('myTensor'); // load tensor