xy-scale 1.0.9 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/index.js +2 -1
- package/package.json +5 -1
- package/src/descale.js +0 -6
- package/src/scale.js +13 -32
- package/test/test.js +1 -1
package/README.md
CHANGED
|
@@ -64,7 +64,9 @@ Designed for production environments, this function parses and scales feature da
|
|
|
64
64
|
- `configX`: Scaling configuration for production data.
|
|
65
65
|
- `keyNamesX`: Key names reflecting feature weights.
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Helper Functions for Custom Data Parsing
|
|
68
70
|
|
|
69
71
|
### `xCallbackFunc`
|
|
70
72
|
|
|
@@ -75,6 +77,21 @@ The `xCallbackFunc` function is used to extract specific feature values from eac
|
|
|
75
77
|
The `yCallbackFunc` function defines the target output (or Y) that the machine learning model will learn to predict. This function typically creates Y by comparing each row of data with a future data point, which is especially useful in time-series data for predictive tasks. In our example, `yCallbackFunc` generates Y based on changes between the current and next rows, which can help the model learn to predict directional trends.
|
|
76
78
|
|
|
77
79
|
|
|
80
|
+
### 3. `descaleArrayObj`
|
|
81
|
+
|
|
82
|
+
The `descaleArrayObj` function reverses the scaling applied to a dataset, reconstructing the original values from the scaled data. It supports both normalization and standardization approaches, making it compatible with the scaled outputs of `parseTrainingXY` and `parseProductionX`.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
#### Parameters:
|
|
86
|
+
- `scaled`: scaled array returned from `parseTrainingXY` (`trainX`, `trainY`, `testX` or `testY`) or `parseProductionX` (`X`).
|
|
87
|
+
- `config`: config object returned from `parseTrainingXY` (`configX`, `configY`) or `parseProductionX` (`configX`).
|
|
88
|
+
- `keyNames`: keyNames array returned from `parseTrainingXY` (`keyNamesX`, `keyNamesY`) or `parseProductionX` (`keyNamesX`).
|
|
89
|
+
- `timeSteps`: input numeric timeSteps param submited to `parseTrainingXY` or `parseProductionX`. Defaults to 0.
|
|
90
|
+
|
|
91
|
+
#### Returns:
|
|
92
|
+
|
|
93
|
+
The output of this function in an array of objects similar or equal to the input array of objects submited to `parseTrainingXY` or `parseProductionX`.
|
|
94
|
+
|
|
78
95
|
---
|
|
79
96
|
|
|
80
97
|
## Usage Examples
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xy-scale",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"main": "./index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -13,5 +13,9 @@
|
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"webpack": "^5.96.1",
|
|
15
15
|
"webpack-cli": "^5.1.4"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/jaimelias/xy-scale.git"
|
|
16
20
|
}
|
|
17
21
|
}
|
package/src/descale.js
CHANGED
|
@@ -2,14 +2,8 @@ import { timeStepsToArray } from './timeSteps.js';
|
|
|
2
2
|
|
|
3
3
|
export const descaleArrayObj = ({ scaled, config, keyNames, timeSteps = 0 }) => {
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
5
|
const { min, max, std, mean, approach, inputTypes, uniqueStringIndexes } = config;
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
console.log('timeStepsToArray', timeStepsToArray(scaled, timeSteps)[0])
|
|
12
|
-
|
|
13
7
|
// Initialize the descaled output array
|
|
14
8
|
const descaledOutput = timeStepsToArray(scaled, timeSteps).map(scaledRow => {
|
|
15
9
|
const originalObj = {};
|
package/src/scale.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
1
|
export const scaleArrayObj = ({arrObj, weights = {}, forceScaling = null}) => {
|
|
4
2
|
|
|
5
|
-
if(forceScaling !== null
|
|
6
|
-
|
|
7
|
-
throw Error('forceScalling should be null, "normalization" or "standardization"')
|
|
3
|
+
if (forceScaling !== null && forceScaling !== 'normalization' && forceScaling !== 'standardization') {
|
|
4
|
+
throw Error('forceScaling should be null, "normalization" or "standardization"');
|
|
8
5
|
}
|
|
9
6
|
|
|
10
7
|
const n = arrObj.length;
|
|
11
8
|
|
|
12
9
|
if (n === 0) {
|
|
13
|
-
// If the input array is empty, return empty outputs
|
|
14
10
|
return {
|
|
15
11
|
scaledOutput: [],
|
|
16
12
|
scaledConfig: {},
|
|
@@ -18,36 +14,22 @@ export const scaleArrayObj = ({arrObj, weights = {}, forceScaling = null}) => {
|
|
|
18
14
|
};
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
// Get the feature names (keys) from the first object
|
|
22
17
|
const keyNames = Object.keys(arrObj[0]);
|
|
23
18
|
|
|
24
|
-
// **Loop 1: Compute weights for each keyName**
|
|
25
19
|
const keyNameWeights = keyNames.map(key => {
|
|
26
|
-
|
|
27
|
-
const weight = weights[key];
|
|
28
|
-
if (weight <= 0) {
|
|
29
|
-
throw new Error(`Weight for key "${key}" must be positive.`);
|
|
30
|
-
}
|
|
31
|
-
return weight;
|
|
32
|
-
} else {
|
|
33
|
-
return 1; // Default weight
|
|
34
|
-
}
|
|
20
|
+
return weights.hasOwnProperty(key) ? Math.max(weights[key], 1) : 1;
|
|
35
21
|
});
|
|
36
22
|
|
|
37
23
|
const totalColumns = keyNameWeights.reduce((sum, weight) => sum + weight, 0);
|
|
38
24
|
|
|
39
|
-
// **Loop 2: Build the new keyNames array with weights applied**
|
|
40
25
|
const outputKeyNames = new Array(totalColumns);
|
|
41
26
|
let idx = 0;
|
|
42
27
|
for (let i = 0; i < keyNames.length; i++) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
for (let w = 0; w < weight; w++) {
|
|
46
|
-
outputKeyNames[idx++] = key;
|
|
28
|
+
for (let w = 0; w < keyNameWeights[i]; w++) {
|
|
29
|
+
outputKeyNames[idx++] = keyNames[i];
|
|
47
30
|
}
|
|
48
31
|
}
|
|
49
32
|
|
|
50
|
-
// Initialize variables for scaling
|
|
51
33
|
const inputTypes = {};
|
|
52
34
|
const min = {};
|
|
53
35
|
const max = {};
|
|
@@ -57,7 +39,6 @@ export const scaleArrayObj = ({arrObj, weights = {}, forceScaling = null}) => {
|
|
|
57
39
|
const uniqueStringIndexes = {};
|
|
58
40
|
const counts = {};
|
|
59
41
|
|
|
60
|
-
// **Loop 3: Initialize variables for each key**
|
|
61
42
|
for (const key of keyNames) {
|
|
62
43
|
const firstValue = arrObj[0][key];
|
|
63
44
|
inputTypes[key] = typeof firstValue;
|
|
@@ -73,7 +54,6 @@ export const scaleArrayObj = ({arrObj, weights = {}, forceScaling = null}) => {
|
|
|
73
54
|
counts[key] = 0;
|
|
74
55
|
}
|
|
75
56
|
|
|
76
|
-
// **Loop 4: Single pass to process data**
|
|
77
57
|
for (const obj of arrObj) {
|
|
78
58
|
for (const key of keyNames) {
|
|
79
59
|
let value = obj[key];
|
|
@@ -84,11 +64,11 @@ export const scaleArrayObj = ({arrObj, weights = {}, forceScaling = null}) => {
|
|
|
84
64
|
uniqueIndexes[value] = Object.keys(uniqueIndexes).length;
|
|
85
65
|
}
|
|
86
66
|
value = uniqueIndexes[value];
|
|
87
|
-
obj[key] = value;
|
|
67
|
+
obj[key] = value;
|
|
88
68
|
}
|
|
89
69
|
|
|
90
|
-
|
|
91
|
-
|
|
70
|
+
min[key] = Math.min(min[key], value);
|
|
71
|
+
max[key] = Math.max(max[key], value);
|
|
92
72
|
|
|
93
73
|
counts[key]++;
|
|
94
74
|
const delta = value - mean[key];
|
|
@@ -97,20 +77,19 @@ export const scaleArrayObj = ({arrObj, weights = {}, forceScaling = null}) => {
|
|
|
97
77
|
}
|
|
98
78
|
}
|
|
99
79
|
|
|
100
|
-
// **Loop 5: Finalize standard deviation and decide scaling approach**
|
|
101
80
|
const std = {};
|
|
102
81
|
for (const key of keyNames) {
|
|
103
82
|
std[key] = counts[key] > 1 ? Math.sqrt(M2[key] / (counts[key] - 1)) : 0;
|
|
104
83
|
|
|
105
|
-
// Apply forceScaling if specified, else use automatic selection
|
|
106
84
|
if (forceScaling === 'normalization' || forceScaling === 'standardization') {
|
|
107
85
|
approach[key] = forceScaling;
|
|
86
|
+
} else if (min[key] === 0 && max[key] === 1) {
|
|
87
|
+
approach[key] = 'none'; // No scaling required
|
|
108
88
|
} else {
|
|
109
89
|
approach[key] = std[key] < 1 ? 'normalization' : 'standardization';
|
|
110
90
|
}
|
|
111
91
|
}
|
|
112
92
|
|
|
113
|
-
// **Loop 6: Create scaled and reweighted output**
|
|
114
93
|
const scaledOutput = new Array(n);
|
|
115
94
|
for (let i = 0; i < n; i++) {
|
|
116
95
|
const obj = arrObj[i];
|
|
@@ -125,7 +104,9 @@ export const scaleArrayObj = ({arrObj, weights = {}, forceScaling = null}) => {
|
|
|
125
104
|
const stdValue = std[key];
|
|
126
105
|
|
|
127
106
|
let scaledValue;
|
|
128
|
-
if (approach[key] === '
|
|
107
|
+
if (approach[key] === 'none') {
|
|
108
|
+
scaledValue = value; // No scaling
|
|
109
|
+
} else if (approach[key] === 'normalization') {
|
|
129
110
|
scaledValue = maxValue !== minValue ? (value - minValue) / (maxValue - minValue) : 0;
|
|
130
111
|
} else {
|
|
131
112
|
scaledValue = stdValue !== 0 ? (value - meanValue) / stdValue : 0;
|
package/test/test.js
CHANGED
|
@@ -52,7 +52,7 @@ const test = async () => {
|
|
|
52
52
|
|
|
53
53
|
//console.log(JSON.stringify(trainingData))
|
|
54
54
|
|
|
55
|
-
console.log('testX', testX
|
|
55
|
+
console.log('testX', testX.slice(-2))
|
|
56
56
|
const descaled = descaleArrayObj({scaled: testX, config: configX, keyNames: keyNamesX, timeSteps})
|
|
57
57
|
|
|
58
58
|
//comparing descaled values with the last values of input myArray
|