Skip to content

Commit 834e22f

Browse files
committed
* avoid passing around dataRaw where possible.
* don't return values which are not used. * renamed some `get` methods to `set`.
1 parent 190fb7a commit 834e22f

File tree

3 files changed

+88
-175
lines changed

3 files changed

+88
-175
lines changed

src/NeuralNetwork/NeuralNetworkData.js

Lines changed: 60 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ class NeuralNetworkData {
2525
// methods
2626
// summarize data
2727
this.createMetadata = this.createMetadata.bind(this);
28-
this.getDataStats = this.getDataStats.bind(this);
28+
this.setDataStats = this.setDataStats.bind(this);
2929
this.getInputMetaStats = this.getInputMetaStats.bind(this);
30-
this.getDataUnits = this.getDataUnits.bind(this);
31-
this.getInputMetaUnits = this.getInputMetaUnits.bind(this);
32-
this.getDTypesFromData = this.getDTypesFromData.bind(this);
30+
this.setDataUnits = this.setDataUnits.bind(this);
31+
this.setInputMetaUnits = this.setInputMetaUnits.bind(this);
32+
this.setDTypesFromData = this.setDTypesFromData.bind(this);
3333
// add data
3434
this.addData = this.addData.bind(this);
3535
// data conversion
@@ -41,7 +41,7 @@ class NeuralNetworkData {
4141
this.unnormalizeArray = this.unnormalizeArray.bind(this);
4242
// one hot
4343
this.applyOneHotEncodingsToDataRaw = this.applyOneHotEncodingsToDataRaw.bind(this);
44-
this.getDataOneHot = this.getDataOneHot.bind(this);
44+
this.setDataOneHot = this.setDataOneHot.bind(this);
4545
this.getInputMetaOneHot = this.getInputMetaOneHot.bind(this);
4646
this.createOneHotEncodings = this.createOneHotEncodings.bind(this);
4747
// Saving / loading data
@@ -66,25 +66,22 @@ class NeuralNetworkData {
6666
* 2. getting the min and max from the data
6767
* 3. getting the oneHot encoded values
6868
* 4. getting the inputShape and outputUnits from the data
69-
* @param {*} dataRaw
70-
* @param {*} inputShape
71-
* TODO: don't need to pass around dataRaw as an argument
69+
* @param {number[]} [inputShape]
7270
*/
73-
createMetadata(dataRaw, inputShape = null) {
74-
if (!dataRaw.length) {
71+
createMetadata(inputShape = null) {
72+
if (!this.data.raw.length) {
7573
throw new Error('Cannot create metadata because no data has been added.');
7674
}
7775
// get the data type for each property
78-
this.getDTypesFromData(dataRaw);
76+
this.setDTypesFromData();
7977
// get the stats - min, max
80-
this.getDataStats(dataRaw);
78+
this.setDataStats();
8179
// onehot encode
82-
this.getDataOneHot(dataRaw);
80+
this.setDataOneHot();
8381
// calculate the input units from the data
84-
this.getDataUnits(dataRaw, inputShape);
82+
this.setDataUnits(inputShape);
8583

8684
this.isMetadataReady = true;
87-
return { ...this.meta };
8885
}
8986

9087
/*
@@ -94,47 +91,35 @@ class NeuralNetworkData {
9491
*/
9592

9693
/**
94+
* @private
9795
* get stats about the data
98-
* @param {*} dataRaw
9996
*/
100-
getDataStats(dataRaw) {
101-
const meta = Object.assign({}, this.meta);
102-
103-
const inputMeta = this.getInputMetaStats(dataRaw, meta.inputs, 'xs');
104-
const outputMeta = this.getInputMetaStats(dataRaw, meta.outputs, 'ys');
105-
106-
meta.inputs = inputMeta;
107-
meta.outputs = outputMeta;
108-
109-
this.meta = {
110-
...this.meta,
111-
...meta,
112-
};
113-
114-
return meta;
97+
setDataStats() {
98+
// TODO: I don't like that this overwrites the existing value -Linda
99+
this.meta.inputs = this.getInputMetaStats(this.meta.inputs, 'xs');
100+
this.meta.outputs = this.getInputMetaStats(this.meta.outputs, 'ys');
115101
}
116102

117103
/**
104+
* @private
118105
* getRawStats
119106
* get back the min and max of each label
120-
* @param {*} dataRaw
121107
* @param {*} inputOrOutputMeta
122108
* @param {*} xsOrYs
123109
*/
124-
// eslint-disable-next-line no-unused-vars, class-methods-use-this
125-
getInputMetaStats(dataRaw, inputOrOutputMeta, xsOrYs) {
110+
getInputMetaStats(inputOrOutputMeta, xsOrYs) {
126111
const inputMeta = Object.assign({}, inputOrOutputMeta);
127112

128113
Object.keys(inputMeta).forEach(k => {
129114
if (inputMeta[k].dtype === 'string') {
130115
inputMeta[k].min = 0;
131116
inputMeta[k].max = 1;
132117
} else if (inputMeta[k].dtype === 'number') {
133-
const dataAsArray = dataRaw.map(item => item[xsOrYs][k]);
118+
const dataAsArray = this.data.raw.map(item => item[xsOrYs][k]);
134119
inputMeta[k].min = nnUtils.getMin(dataAsArray);
135120
inputMeta[k].max = nnUtils.getMax(dataAsArray);
136121
} else if (inputMeta[k].dtype === 'array') {
137-
const dataAsArray = dataRaw.map(item => item[xsOrYs][k]).flat();
122+
const dataAsArray = this.data.raw.map(item => item[xsOrYs][k]).flat();
138123
inputMeta[k].min = nnUtils.getMin(dataAsArray);
139124
inputMeta[k].max = nnUtils.getMax(dataAsArray);
140125
}
@@ -144,41 +129,23 @@ class NeuralNetworkData {
144129
}
145130

146131
/**
132+
* @private
147133
* get the data units, inputshape and output units
148-
* @param {*} dataRaw
134+
* @param {*} arrayShape
149135
*/
150-
getDataUnits(dataRaw, _arrayShape = null) {
151-
const arrayShape = _arrayShape !== null ? _arrayShape : undefined;
152-
const meta = Object.assign({}, this.meta);
153-
136+
setDataUnits(arrayShape) {
154137
// if the data has a shape pass it in
155-
let inputShape;
156-
if (arrayShape) {
157-
inputShape = arrayShape;
158-
} else {
159-
inputShape = [this.getInputMetaUnits(dataRaw, meta.inputs)].flat();
160-
}
161-
162-
const outputShape = this.getInputMetaUnits(dataRaw, meta.outputs);
163-
164-
meta.inputUnits = inputShape;
165-
meta.outputUnits = outputShape;
166-
167-
this.meta = {
168-
...this.meta,
169-
...meta,
170-
};
171-
172-
return meta;
138+
this.meta.inputUnits = arrayShape ?? [this.setInputMetaUnits(this.meta.inputs)].flat();
139+
this.meta.outputUnits = this.setInputMetaUnits(this.meta.outputs);
173140
}
174141

175142
/**
143+
* @private
176144
* get input
177145
* @param {*} _inputsMeta
178-
* @param {*} _dataRaw
179146
*/
180-
// eslint-disable-next-line class-methods-use-this, no-unused-vars
181-
getInputMetaUnits(_dataRaw, _inputsMeta) {
147+
// eslint-disable-next-line class-methods-use-this
148+
setInputMetaUnits(_inputsMeta) {
182149
let units = 0;
183150
const inputsMeta = Object.assign({}, _inputsMeta);
184151

@@ -202,18 +169,19 @@ class NeuralNetworkData {
202169
}
203170

204171
/**
205-
* getDTypesFromData
172+
* @private
173+
* setDTypesFromData
206174
* gets the data types of the data we're using
207175
* important for handling oneHot
208176
*/
209-
getDTypesFromData(_dataRaw) {
177+
setDTypesFromData() {
210178
const meta = {
211179
...this.meta,
212180
inputs: {},
213181
outputs: {},
214182
};
215183

216-
const sample = _dataRaw[0];
184+
const sample = this.data.raw[0];
217185
const xs = Object.keys(sample.xs);
218186
const ys = Object.keys(sample.ys);
219187

@@ -233,8 +201,6 @@ class NeuralNetworkData {
233201
// otherwise throw an error
234202

235203
this.meta = meta;
236-
237-
return meta;
238204
}
239205

240206
/**
@@ -244,6 +210,7 @@ class NeuralNetworkData {
244210
*/
245211

246212
/**
213+
* @public - used by nn
247214
* Add Data
248215
* @param {object} xInputObj, {key: value}, key must be the name of the property value must be a String, Number, or Array
249216
* @param {*} yInputObj, {key: value}, key must be the name of the property value must be a String, Number, or Array
@@ -262,12 +229,13 @@ class NeuralNetworkData {
262229
*/
263230

264231
/**
232+
* @public - used by nn
265233
* convertRawToTensors
266234
* converts array of {xs, ys} to tensors
267235
* @param {*} _dataRaw
268236
* @param {*} meta
237+
* TODO: requires the nn to pass in the training data as an argument -- why?
269238
*/
270-
// eslint-disable-next-line class-methods-use-this, no-unused-vars
271239
convertRawToTensors(dataRaw) {
272240
const meta = Object.assign({}, this.meta);
273241
const dataLength = dataRaw.length;
@@ -313,30 +281,24 @@ class NeuralNetworkData {
313281
*/
314282

315283
/**
284+
* @public - used by nn
316285
* normalize the dataRaw input
317-
* @param {*} dataRaw
318286
*/
319-
normalizeDataRaw(dataRaw) {
320-
const meta = Object.assign({}, this.meta);
321-
322-
const normXs = this.normalizeInputData(dataRaw, meta.inputs, 'xs');
323-
const normYs = this.normalizeInputData(dataRaw, meta.outputs, 'ys');
324-
325-
const normalizedData = nnUtils.zipArrays(normXs, normYs);
287+
normalizeDataRaw() {
288+
const normXs = this.normalizeInputData(this.meta.inputs, 'xs');
289+
const normYs = this.normalizeInputData(this.meta.outputs, 'ys');
326290

327-
return normalizedData;
291+
return nnUtils.zipArrays(normXs, normYs);
328292
}
329293

330294
/**
331-
* normalizeRaws
332-
* @param {*} dataRaw
295+
* @private
333296
* @param {*} inputOrOutputMeta
334297
* @param {*} xsOrYs
335298
*/
336-
// eslint-disable-next-line no-unused-vars, class-methods-use-this
337-
normalizeInputData(dataRaw, inputOrOutputMeta, xsOrYs) {
299+
normalizeInputData(inputOrOutputMeta, xsOrYs) {
338300
// the data length
339-
const dataLength = dataRaw.length;
301+
const dataLength = this.data.raw.length;
340302
// the copy of the inputs.meta[inputOrOutput]
341303
const inputMeta = Object.assign({}, inputOrOutputMeta);
342304

@@ -349,7 +311,7 @@ class NeuralNetworkData {
349311
max: inputMeta[k].max,
350312
};
351313

352-
const dataAsArray = dataRaw.map(item => item[xsOrYs][k]);
314+
const dataAsArray = this.data.raw.map(item => item[xsOrYs][k]);
353315
// depending on the input type, normalize accordingly
354316
if (inputMeta[k].dtype === 'string') {
355317
options.legend = inputMeta[k].legend;
@@ -378,7 +340,7 @@ class NeuralNetworkData {
378340
}
379341

380342
/**
381-
* normalizeArray
343+
* @public - used by nn
382344
* @param {*} _input
383345
* @param {*} _options
384346
*/
@@ -408,7 +370,7 @@ class NeuralNetworkData {
408370
}
409371

410372
/**
411-
* unNormalizeArray
373+
* @public but not used anywhere
412374
* @param {*} _input
413375
* @param {*} _options
414376
*/
@@ -451,16 +413,17 @@ class NeuralNetworkData {
451413
*/
452414

453415
/**
416+
* @public - used by nn
454417
* applyOneHotEncodingsToDataRaw
455418
* does not set this.data.raws
456419
* but rather returns them
457420
* @param {*} _dataRaw
458421
* @param {*} _meta
459422
*/
460-
applyOneHotEncodingsToDataRaw(dataRaw) {
423+
applyOneHotEncodingsToDataRaw() {
461424
const meta = Object.assign({}, this.meta);
462425

463-
const output = dataRaw.map(row => {
426+
const output = this.data.raw.map(row => {
464427
const xs = {
465428
...row.xs,
466429
};
@@ -490,35 +453,21 @@ class NeuralNetworkData {
490453
}
491454

492455
/**
493-
* getDataOneHot
456+
* @private
494457
* creates onehot encodings for the input and outputs
495458
* and adds them to the meta info
496-
* @param {*} dataRaw
497459
*/
498-
getDataOneHot(dataRaw) {
499-
const meta = Object.assign({}, this.meta);
500-
501-
const inputMeta = this.getInputMetaOneHot(dataRaw, meta.inputs, 'xs');
502-
const outputMeta = this.getInputMetaOneHot(dataRaw, meta.outputs, 'ys');
503-
504-
meta.inputs = inputMeta;
505-
meta.outputs = outputMeta;
506-
507-
this.meta = {
508-
...this.meta,
509-
...meta,
510-
};
511-
512-
return meta;
460+
setDataOneHot() {
461+
this.meta.inputs = this.getInputMetaOneHot(this.meta.inputs, 'xs');
462+
this.meta.outputs = this.getInputMetaOneHot(this.meta.outputs, 'ys');
513463
}
514464

515465
/**
516-
* getOneHotMeta
466+
* @private
517467
* @param {*} _inputsMeta
518-
* @param {*} _dataRaw
519468
* @param {*} xsOrYs
520469
*/
521-
getInputMetaOneHot(_dataRaw, _inputsMeta, xsOrYs) {
470+
getInputMetaOneHot(_inputsMeta, xsOrYs) {
522471
const inputsMeta = Object.assign({}, _inputsMeta);
523472

524473
Object.entries(inputsMeta).forEach(arr => {
@@ -528,7 +477,7 @@ class NeuralNetworkData {
528477
const { dtype } = arr[1];
529478

530479
if (dtype === 'string') {
531-
const uniqueVals = [...new Set(_dataRaw.map(obj => obj[xsOrYs][key]))];
480+
const uniqueVals = [...new Set(this.data.raw.map(obj => obj[xsOrYs][key]))];
532481
const oneHotMeta = this.createOneHotEncodings(uniqueVals);
533482
inputsMeta[key] = {
534483
...inputsMeta[key],
@@ -587,7 +536,7 @@ class NeuralNetworkData {
587536
*/
588537
async loadData(filesOrPath, inputLabels, outputLabels) {
589538
const dataArray = await loadData(filesOrPath);
590-
this.data.raw = this.formatRawData(dataArray, inputLabels, outputLabels);
539+
this.formatRawData(dataArray, inputLabels, outputLabels);
591540
}
592541

593542
/**
@@ -704,7 +653,8 @@ class NeuralNetworkData {
704653
}
705654

706655
// create an array of json objects [{xs,ys}]
707-
const result = dataArray.map((item, idx) => {
656+
// set this.data.raw
657+
this.data.raw = dataArray.map((item, idx) => {
708658
const output = {
709659
xs: {},
710660
ys: {},
@@ -728,11 +678,6 @@ class NeuralNetworkData {
728678

729679
return output;
730680
});
731-
732-
// set this.data.raw
733-
this.data.raw = result;
734-
735-
return result;
736681
}
737682

738683
/**

0 commit comments

Comments
 (0)