Разделение данных на обучающую и тестовую выборки является фундаментальным этапом при построении нейронных сетей с использованием библиотеки ConvNetJS. Правильное распределение данных позволяет оценить обобщающую способность модели и предотвратить переобучение.
Обучающая выборка (training set) используется для непосредственного обучения нейронной сети. Она содержит большинство примеров, на которых сеть будет корректировать свои веса через алгоритмы обратного распространения ошибки.
Тестовая выборка (test set) применяется исключительно для оценки качества обученной модели. Она не участвует в процессе обучения и позволяет объективно измерить способность сети к генерализации на новые данные.
Важные моменты:
function splitData(data, testRatio) {
let shuffled = data.slice();
for (let i = shuffled.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
let testSize = Math.floor(data.length * testRatio);
let testSet = shuffled.slice(0, testSize);
let trainSet = shuffled.slice(testSize);
return {trainSet, testSet};
}
data — исходный массив объектов с признаками и
метками.testRatio — доля данных для тестовой выборки.Для задач классификации важно, чтобы пропорции классов в обучающей и тестовой выборках соответствовали исходному распределению. Это предотвращает смещение метрик при редких классах.
function stratifiedSplit(data, labels, testRatio) {
let labelMap = {};
for (let i = 0; i < data.length; i++) {
if (!labelMap[labels[i]]) labelMap[labels[i]] = [];
labelMap[labels[i]].push(data[i]);
}
let trainSet = [];
let testSet = [];
for (let label in labelMap) {
let items = labelMap[label];
let testSize = Math.floor(items.length * testRatio);
for (let i = 0; i < items.length; i++) {
if (i < testSize) testSet.push(items[i]);
else trainSet.push(items[i]);
}
}
return {trainSet, testSet};
}
ConvNetJS использует объект Vol для представления
входных данных. После разделения выборок данные преобразуются в объекты
Vol с соответствующими метками для обучения и
тестирования.
let trainData = trainSet.map(d => ({x: new convnetjs.Vol(d.input), y: d.label}));
let testData = testSet.map(d => ({x: new convnetjs.Vol(d.input), y: d.label}));
d.input — массив признаков для одного примера.d.label — числовая метка класса.trainer.train() и trainer.trainBatch().Пример организации процесса обучения с контролем тестовой выборки:
let trainer = new convnetjs.SGDTrainer(net, {learning_rate:0.01, momentum:0.9, batch_size:10, l2_decay:0.001});
for (let epoch = 0; epoch < 50; epoch++) {
for (let i = 0; i < trainData.length; i++) {
trainer.train(trainData[i].x, trainData[i].y);
}
// Проверка качества на тестовой выборке
let correct = 0;
for (let i = 0; i < testData.length; i++) {
let predicted = net.forward(testData[i].x).w.indexOf(Math.max(...net.forward(testData[i].x).w));
if (predicted === testData[i].y) correct++;
}
console.log(`Эпоха ${epoch}: точность на тестовой выборке ${(correct/testData.length*100).toFixed(2)}%`);
}
trainData только для обучения,
testData только для оценки — обязательное условие.Разделение данных на обучающую и тестовую выборки в ConvNetJS напрямую влияет на корректность оценки нейронной сети и предотвращение переобучения. Грамотная организация этого этапа обеспечивает точность и стабильность обучения, особенно при работе с реальными наборами данных.