Skip to content

Commit dd804e8

Browse files
committed
finish feature normalization and multivariate linear regression
1 parent 4ed9255 commit dd804e8

File tree

3 files changed

+50
-58
lines changed

3 files changed

+50
-58
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
},
1818
"dependencies": {
1919
"csv-to-array-matrix": "^0.1.1",
20-
"fast-csv": "^2.4.1",
2120
"mathjs": "^3.16.5"
2221
}
2322
}

src/index.js

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ import math from 'mathjs';
22
import csvToMatrix from 'csv-to-array-matrix';
33

44
import {
5-
getDimension,
6-
getSubset,
7-
getMeanByVector,
8-
getStdByVector,
9-
setVector,
5+
getDimensionSize,
6+
getMeanAsRowVector,
7+
getStdAsRowVector,
108
pushVector,
119
} from './util';
1210

@@ -17,10 +15,15 @@ function init(matrix) {
1715
// Part 0: Preparation
1816
console.log('Part 0: Preparation ...\n');
1917

20-
let X = getSubset(matrix, ':, 1:2');
21-
let y = getSubset(matrix, ':, 3');
22-
let m = getDimension(y, 1);
23-
let n = getDimension(y, 2);
18+
let X = math.eval('matrix[:, 1:2]', {
19+
matrix,
20+
});
21+
let y = math.eval('matrix[:, 3]', {
22+
matrix,
23+
});
24+
25+
let m = getDimensionSize(y, 1);
26+
let n = getDimensionSize(y, 2);
2427

2528
// Part 1: Feature Normalization
2629
console.log('Part 1: Feature Normalization ...\n');
@@ -43,60 +46,56 @@ function init(matrix) {
4346
const ALPHA = 0.01;
4447
const ITERATIONS = 400;
4548

46-
let theta = math.zeros(3, 1).valueOf();
49+
let theta = [[0], [0], [0]];
4750
theta = gradientDescentMulti(XNorm, y, theta, ALPHA, ITERATIONS);
4851

4952
console.log('theta: ', theta);
5053
console.log('\n');
5154
}
5255

5356
function featureNormalize(X) {
54-
const mu = getMeanByVector(X);
55-
const sigma = getStdByVector(X); // alternative: range
57+
const mu = getMeanAsRowVector(X);
58+
const sigma = getStdAsRowVector(X); // alternative: range
5659

5760
// n = features
58-
const n = getDimension(X, 2);
61+
const n = getDimensionSize(X, 2);
5962
for (let i = 0; i < n; i++) {
6063

61-
// take feature column by index i and subtract with mean with index i from mean vector
62-
let xMinusMean = math.subtract(getSubset(X, `:, ${i + 1}`), mu[i]);
63-
// put normalized feature column by dividing the meaned vector with the standard deviation
64-
let normalizedVector = math.divide(xMinusMean, sigma[i]);
64+
let featureVector = math.eval(`X[:, ${i + 1}]`, {
65+
X,
66+
});
67+
68+
let featureMeanVector = math.eval('featureVector - mu', {
69+
featureVector,
70+
mu: mu[i]
71+
});
72+
73+
let normalizedVector = math.eval('featureMeanVector / sigma', {
74+
featureMeanVector,
75+
sigma: sigma[i],
76+
});
6577

66-
X = setVector(X, i, normalizedVector);
78+
math.eval(`X[:, ${i + 1}] = normalizedVector`, {
79+
X,
80+
normalizedVector,
81+
});
6782
}
6883

6984
return { XNorm: X, mu, sigma };
7085
}
7186

7287
function gradientDescentMulti(X, y, theta, ALPHA, ITERATIONS) {
73-
const m = getDimension(y, 1);
88+
const m = getDimensionSize(y, 1);
7489

7590
for (let i = 0; i < ITERATIONS; i++) {
76-
// Octave:
77-
// theta = theta - ALPHA / m * ((X * theta - y)' * X)';
78-
79-
theta = math.subtract(
91+
theta = math.eval(`theta - ALPHA / m * ((X * theta - y)' * X)'`, {
8092
theta,
81-
math.multiply(
82-
(ALPHA / m),
83-
math.transpose(
84-
math.multiply(
85-
math.transpose(
86-
math.subtract(
87-
math.multiply(
88-
X,
89-
theta
90-
),
91-
y
92-
)
93-
),
94-
X
95-
)
96-
)
97-
)
98-
);
93+
ALPHA,
94+
m,
95+
X,
96+
y,
97+
});
9998
}
10099

101100
return theta;
102-
}
101+
}

src/util.js

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import math from 'mathjs';
22

3-
export const getSubset = (matrix, selector) =>
4-
math.eval(`matrix[${selector}]`, { matrix });
5-
63
export const pushVector = (matrix, index, vector) => {
74
const extendedMatrix = math
85
.ones([
9-
getDimension(matrix, 1),
10-
getDimension(matrix, 2) + 1
6+
getDimensionSize(matrix, 1),
7+
getDimensionSize(matrix, 2) + 1
118
])
129
.valueOf();
1310

@@ -24,22 +21,19 @@ export const pushVector = (matrix, index, vector) => {
2421
}));
2522
};
2623

27-
export const setVector = (matrix, index, vector) =>
28-
matrix.map((row, rowKey) => row.map((column, columnKey) => index === columnKey ? vector[rowKey][0] : column));
29-
30-
export const getMeanByVector = (matrix) => {
31-
const n = getDimension(matrix, 2);
32-
const vectors = Array(n).fill().map((_, i) => getSubset(matrix, `:, ${i + 1}`));
24+
export const getMeanAsRowVector = (matrix) => {
25+
const n = getDimensionSize(matrix, 2);
26+
const vectors = Array(n).fill().map((_, i) => math.eval(`matrix[:, ${i + 1}]`, { matrix }));
3327
return vectors.reduce((result, vector) => result.concat(math.mean(vector)), []);
3428
};
3529

36-
export const getStdByVector = (matrix) => {
37-
const n = getDimension(matrix, 2);
38-
const vectors = Array(n).fill().map((_, i) => getSubset(matrix, `:, ${i + 1}`));
30+
export const getStdAsRowVector = (matrix) => {
31+
const n = getDimensionSize(matrix, 2);
32+
const vectors = Array(n).fill().map((_, i) => math.eval(`matrix[:, ${i + 1}]`, { matrix }));
3933
return vectors.reduce((result, vector) => result.concat(math.std(vector)), []);
4034
};
4135

42-
export const getDimension = (matrix, dimension) =>
36+
export const getDimensionSize = (matrix, dimension) =>
4337
dimension === 1
4438
? matrix.length
4539
: matrix[0].length;

0 commit comments

Comments
 (0)