Last active
May 9, 2019 07:39
-
-
Save johnkazer/ee7b608b41bee1f67c3db900bd0e1c0a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
exports.start = function (res) { // res being the Express response object, being the server package I used | |
const network = new NN.NeuralNetwork(); | |
let dataTypes = [] | |
let listOfTrainingData = [] | |
let listOfTestData = [] | |
let trainingDataRaw = [] | |
let testDataRaw = [] | |
const trainingOptions = { /* config options */ } | |
var parser = csv({ delimiter: ',' }, function (err, data) { // in general, I find processing of arbitrary data files hard to do with pure functions - so I took some short cuts... | |
if (err || data.length === 0) { | |
return null | |
} else { | |
dataTypes = data[0].slice(0) // not very pure | |
parseTrainingData(data.slice(1)) // this should normally return the completed data - see in-function comments below | |
} | |
}) | |
try { // not really pure either, but I don't know a better way of handling contact with the file system. At least the event-driven code is all in one place | |
const stream = fs.createReadStream(path.join(__dirname, 'data.csv')) | |
stream.pipe(parser) | |
stream.on('close', () => { | |
network.train(definedTrainingDataset(trainingDataRaw), trainingOptions) | |
const nnConfig = network.toJSON() | |
const significantInputs = identifySignificantInputs(nnConfig) | |
fs.writeFileSync('savedNN.json', JSON.stringify(nnConfig, null, 2)) | |
res.send({ msg: '', result: generatedTestResults(testData), keyInputData: significantInputs, testedData: listOfTestData }) | |
}) | |
stream.on('error', (error) => { | |
throw(error) | |
}) | |
} catch (err) { | |
res.send({ msg: err }) | |
} | |
function parseTrainingData (data) { | |
if (data[0][0] === 'TEST') { | |
return parseTestData(data.slice(1)) | |
} else if (data.length === 0) { | |
return // normally a recursive function would return the completed data, but see next comment for why not in this case | |
} else { | |
listOfTrainingData.push(data[0][0]) // not very pure but I'm OK with it for now. Hard to return two new arrays and then two more test data arrays | |
trainingDataRaw.push(data[0].slice(1)) | |
return parseTrainingData(data.slice(1)) | |
} | |
} | |
function parseTestData (data) { | |
if (data.length === 0) { | |
return // see above regarding return values | |
} else { | |
listOfTestData.push(data[0][0]) // not very pure either! | |
testDataRaw.push(data[0].slice(1)) | |
return parseTestData(data.slice(1)) | |
} | |
} | |
function identifySignificantInputs (nnConfigData) { | |
const listOfHiddenNodes = Object.values(nnConfigData.layers[1]) | |
const summedWeights = listOfHiddenNodes.map((node) => { | |
return Object.values(node.weights).reduce(function sumWeights (sum, weight) { | |
return sum + weight | |
}) | |
}) | |
const numWeights = summedWeights.length > 10 ? 10 : summedWeights.length | |
const topTen = summedWeights.sort().slice(summedWeights.length - numWeights) | |
return topTen.map((summedWeight) => { // what is actually wanted are the indexes of the highest 10 summedWeights values | |
return dataTypes[summedWeights.indexOf(summedWeight)] // then match these to the original data (column) names | |
}) | |
} | |
function definedTrainingDataset(rawData) { | |
return rawData.map((data) => { | |
const input = data.slice(0, data.length - 1) | |
const output = data.slice(data.length - 1) // the CSV defines the desired neural network output as the last item in a row | |
return { input, output } // Brain.js specifies this type of object for the training set | |
}) | |
} | |
function generatedTestResults(dataToTest) { | |
return dataToTest.map((dataPoint) => { | |
const input = dataPoint.slice(0, dataPoint.length - 1) | |
const output = dataPoint.slice(dataPoint.length - 1) // output is last item in a row | |
return { actual: network.run(input), desired: output } // not pure, as running the test function here - probably should segregate this better | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment