<commit_before>// Copyright(c) 2016 <NAME>
// Distributed under the MIT License (See accompanying file LICENSE.md file or copy at http://opensource.org/licenses/MIT).
#include "test_neural/pch.h"
#include "test/unit/coTest.h"
#include "neural/network/coNeuralNet.h"
#include "neural/network/coNeuralLayer.h"
#include "neural/process/coNeuralNet_f.h"
#include "neural/process/training/coNeuralDataSet.h"
#include "neural/process/training/coNeuralTrainingNet.h"
#include "neural/process/training/coNeuralTrainingNet_f.h"
#include "neural/process/compute/coNeuralComputeOutputs.h"
#include "math/scalar/coFloat_f.h"

coTEST(coNeuralNet, Init)
{
	coNeuralLayer data(1, 1);
	coEXPECT(data.Init(coNeuralLayer::InitConfig()));
	coArray<coNeuralLayer*> layerDatas = { &data };
	coNeuralNet net(layerDatas);
	coEXPECT(net.Init(coNeuralNet::InitConfig()));
}

coTEST(coNeuralNet, TrainALine)
{
	const coFloat a = 7.0f;
	const coFloat b = 17.0f;
	const coFloat xMin = -100.0f;
	const coFloat xMax = 100.0f;
	const coFloat xRange = xMax - xMin;
	const coFloat yMin = a * xMin + b;
	const coFloat yMax = a * xMax + b;
	const coFloat yRange = yMax - yMin;
	//coASSERT(yRange > 0.0f);
	const coFloat desiredError = 0.01f;
	coNeuralLayer data0(1, 8);
	coNeuralLayer data1(8, 1);
	coEXPECT(data0.Init(coNeuralLayer::InitConfig()));
	coEXPECT(data1.Init(coNeuralLayer::InitConfig()));
	coDynamicArray<coNeuralLayer*> layerDatas;
	coPushBack(layerDatas, &data0);
	coPushBack(layerDatas, &data1);
	coNeuralNet net(layerDatas);
	coEXPECT(net.Init(coNeuralNet::InitConfig()));

	coUint32 seed = 777777777;

	auto GetRandomX = [&]()
	{
		return coRand01(seed) * xRange + xMin;
	};
	auto ConvertXToNet = [&](coFloat _x)
	{
		return coClamp01((_x - xMin) / xRange);
	};
	auto ConvertXFromNet = [&](coFloat _x)
	{
		return _x * xRange + xMin;
	};
	auto ConvertYToNet = [&](coFloat _y)
	{
		return coClamp01((_y - yMin) / yRange);
	};
	auto ConvertYFromNet = [&](coFloat _y)
	{
		return _y * yRange + yMin;
	};

	// Train
	{
		const coUint nbSamples = 1000;
		coDynamicArray<coFloat> inputs;
		coDynamicArray<coFloat> outputs;
		{
			coResize(inputs, nbSamples);
			coResize(outputs, nbSamples);
			for (coUint i = 0; i < nbSamples; ++i)
			{
				const coFloat x = GetRandomX();
				inputs[i] = ConvertXToNet(x);
				outputs[i] = ConvertYToNet(a * x + b);
			}
		}

		coNeuralDataSet dataSet;
		{
			dataSet.nbSamples = nbSamples;
			dataSet.inputs = inputs;
			dataSet.outputs = outputs;
		}

		coNeuralTrainingNet trainingNet(net);
		coEXPECT(trainingNet.Init(coObject::InitConfig()));

		coResetWeightsAndBiases(net, seed);

		const coUint nbMaxEpochs = 1000;
		coEXPECT(coTrain(trainingNet, dataSet, desiredError, nbMaxEpochs));
	}

	// Checks
	{
		coDynamicArray<coFloat> outputs;
		coResize(outputs, 1);

		coFloat error = 0.0f;
		coUint nbChecks = 1000;
		for (coUint i = 0; i < nbChecks; ++i)
		{
			const coFloat x = GetRandomX();
			const coFloat input = ConvertXToNet(x);
			coComputeNeuralOutputs(net, { input }, outputs);
			const coFloat output = outputs[0];
			const coFloat expectedOutput = ConvertYToNet(a * x + b);
			error += coPow2(expectedOutput - output);
		}<commit_msg>plot values for the test.<commit_after>// Copyright(c) 2016 <NAME>
// Distributed under the MIT License (See accompanying file LICENSE.md file or copy at http://opensource.org/licenses/MIT).
#include "test_neural/pch.h"
#include "test/unit/coTest.h"
#include "neural/network/coNeuralNet.h"
#include "neural/network/coNeuralLayer.h"
#include "neural/process/coNeuralNet_f.h"
#include "neural/process/training/coNeuralDataSet.h"
#include "neural/process/training/coNeuralTrainingNet.h"
#include "neural/process/training/coNeuralTrainingNet_f.h"
#include "neural/process/compute/coNeuralComputeOutputs.h"
#include "math/scalar/coFloat_f.h"

coTEST(coNeuralNet, Init)
{
	coNeuralLayer data(1, 1);
	coEXPECT(data.Init(coNeuralLayer::InitConfig()));
	coArray<coNeuralLayer*> layerDatas = { &data };
	coNeuralNet net(layerDatas);
	coEXPECT(net.Init(coNeuralNet::InitConfig()));
}

coTEST(coNeuralNet, TrainALine)
{
	const coFloat a = 7.0f;
	const coFloat b = 17.0f;
	const coFloat xMin = -100.0f;
	const coFloat xMax = 100.0f;
	const coFloat xRange = xMax - xMin;
	const coFloat yMin = a * xMin + b;
	const coFloat yMax = a * xMax + b;
	const coFloat yRange = yMax - yMin;

	const coUint nbHiddenNeurons = 4;
	//coASSERT(yRange > 0.0f);
	const coFloat desiredError = 0.01f;
	coNeuralLayer data0(1, nbHiddenNeurons);
	coNeuralLayer data1(nbHiddenNeurons, 1);
	coEXPECT(data0.Init(coNeuralLayer::InitConfig()));
	coEXPECT(data1.Init(coNeuralLayer::InitConfig()));
	coDynamicArray<coNeuralLayer*> layerDatas;
	coPushBack(layerDatas, &data0);
	coPushBack(layerDatas, &data1);
	coNeuralNet net(layerDatas);
	coEXPECT(net.Init(coNeuralNet::InitConfig()));

	coUint32 seed = 777777777;

	auto GetRandomX = [&]()
	{
		return coRand01(seed) * xRange + xMin;
	};
	auto ConvertXToNet = [&](coFloat _x)
	{
		return coClamp01((_x - xMin) / xRange);
	};
	auto ConvertXFromNet = [&](coFloat _x)
	{
		return _x * xRange + xMin;
	};
	auto ConvertYToNet = [&](coFloat _y)
	{
		return coClamp01((_y - yMin) / yRange);
	};
	auto ConvertYFromNet = [&](coFloat _y)
	{
		return _y * yRange + yMin;
	};

	// Train
	{
		const coUint nbSamples = 1000;
		coDynamicArray<coFloat> inputs;
		coDynamicArray<coFloat> outputs;
		{
			coResize(inputs, nbSamples);
			coResize(outputs, nbSamples);
			for (coUint i = 0; i < nbSamples; ++i)
			{
				const coFloat x = GetRandomX();
				inputs[i] = ConvertXToNet(x);
				outputs[i] = ConvertYToNet(a * x + b);
			}
		}

		coNeuralDataSet dataSet;
		{
			dataSet.nbSamples = nbSamples;
			dataSet.inputs = inputs;
			dataSet.outputs = outputs;
		}

		coNeuralTrainingNet trainingNet(net);
		coEXPECT(trainingNet.Init(coObject::InitConfig()));

		coResetWeightsAndBiases(net, seed);

		const coUint nbMaxEpochs = 1000;
		coEXPECT(coTrain(trainingNet, dataSet, desiredError, nbMaxEpochs));
	}

	// Checks
	{
		const coUint nbChecks = 1000;

		coDynamicArray<coFloat> allOutputs; // can be plotted 
		coResize(allOutputs, nbChecks);
		coDynamicArray<coFloat> outputs;
		coResize(outputs, 1);
		
		coFloat error = 0.0f;
		for (coUint i = 0; i < nbChecks; ++i)
		{
			const coFloat x = xMin + xRange * i / (nbChecks - 1);
			const coFloat input = ConvertXToNet(x);
			coComputeNeuralOutputs(net, { input }, outputs);
			const coFloat output = outputs[0];
			allOutputs[i] = output;
			const coFloat expectedOutput = ConvertYToNet(a * x + b);
			error += coPow2(expectedOutput - output);
		}
{'fraction_non_alphanumeric': 0.1363428397132835, 'fraction_numerical': 0.021351227695592497, 'mean_word_length': 4.529510961214165, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1360124', 'n_tokens_mistral': 2771, 'n_tokens_neox': 2531, 'n_words': 516}