echogarden 0.11.12 → 0.11.13
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/data/schemas/options.json +16 -0
- package/dist/api/Alignment.js +2 -2
- package/dist/api/Alignment.js.map +1 -1
- package/dist/api/Recognition.js +2 -2
- package/dist/api/Recognition.js.map +1 -1
- package/dist/api/Synthesis.js +5 -4
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/api/Translation.js +2 -2
- package/dist/api/Translation.js.map +1 -1
- package/dist/audio/AudioUtilities.d.ts +1 -0
- package/dist/audio/AudioUtilities.js +25 -7
- package/dist/audio/AudioUtilities.js.map +1 -1
- package/dist/cli/CLI.js +2 -2
- package/dist/cli/CLI.js.map +1 -1
- package/dist/recognition/WhisperSTT.js +2 -2
- package/dist/recognition/WhisperSTT.js.map +1 -1
- package/dist/subtitles/Subtitles.d.ts +10 -7
- package/dist/subtitles/Subtitles.js +268 -207
- package/dist/subtitles/Subtitles.js.map +1 -1
- package/docs/Options.md +4 -2
- package/package.json +7 -6
- package/src/alignment/DTWMfccSequenceAlignment.ts +43 -0
- package/src/alignment/DTWSequenceAlignment.ts +121 -0
- package/src/alignment/DTWSequenceAlignmentWindowed.ts +210 -0
- package/src/alignment/LevenshteinSequenceAlignment.ts +126 -0
- package/src/alignment/SpeechAlignment.ts +488 -0
- package/src/api/API.ts +12 -0
- package/src/api/APIOptions.ts +15 -0
- package/src/api/Alignment.ts +329 -0
- package/src/api/Common.ts +16 -0
- package/src/api/Denoising.ts +120 -0
- package/src/api/LanguageDetection.ts +286 -0
- package/src/api/Recognition.ts +344 -0
- package/src/api/Synthesis.ts +1735 -0
- package/src/api/Translation.ts +143 -0
- package/src/api/Vad.ts +172 -0
- package/src/audio/AudioBufferConversion.ts +248 -0
- package/src/audio/AudioPlayer.ts +358 -0
- package/src/audio/AudioRecorder.ts +91 -0
- package/src/audio/AudioUtilities.ts +392 -0
- package/src/audio/SoxPath.ts +24 -0
- package/src/cli/CLI.ts +1360 -0
- package/src/cli/CLIConfigFile.ts +91 -0
- package/src/cli/CLILauncher.ts +26 -0
- package/src/cli/CLIOptionsSchema.ts +54 -0
- package/src/cli/CLIParser.ts +41 -0
- package/src/cli/CLIStarter.ts +40 -0
- package/src/codecs/FFMpegTranscoder.ts +214 -0
- package/src/codecs/TIMITCodec.ts +17 -0
- package/src/codecs/WaveCodec.ts +260 -0
- package/src/denoising/RNNoise.ts +95 -0
- package/src/dsp/BiquadFilter.ts +488 -0
- package/src/dsp/FFT.ts +187 -0
- package/src/dsp/MFCC.ts +227 -0
- package/src/dsp/MelSpectogram.ts +145 -0
- package/src/dsp/Rubberband.ts +249 -0
- package/src/dsp/Sonic.ts +59 -0
- package/src/dsp/SpeexResampler.ts +79 -0
- package/src/math/VectorMath.ts +812 -0
- package/src/nlp/ChineseSegmentation.ts +68 -0
- package/src/nlp/CompromiseNLP.ts +113 -0
- package/src/nlp/EspeakPhonemizer.ts +168 -0
- package/src/nlp/IPA.ts +139 -0
- package/src/nlp/JapaneseSegmentation.ts +53 -0
- package/src/nlp/Lexicon.ts +119 -0
- package/src/nlp/PhoneConversion.ts +508 -0
- package/src/nlp/Segmentation.ts +237 -0
- package/src/nlp/TextNormalizer.ts +160 -0
- package/src/recognition/AmazonTranscribeSTT.ts +112 -0
- package/src/recognition/AzureCognitiveServicesSTT.ts +76 -0
- package/src/recognition/GoogleCloudSTT.ts +92 -0
- package/src/recognition/SileroSTT.ts +173 -0
- package/src/recognition/VoskSTT.ts +112 -0
- package/src/recognition/WhisperSTT.ts +1518 -0
- package/src/server/Client.ts +297 -0
- package/src/server/Server.ts +178 -0
- package/src/server/ServerStarter.ts +12 -0
- package/src/server/Worker.ts +400 -0
- package/src/server/WorkerStarter.ts +38 -0
- package/src/speech-language-detection/SileroLanguageDetection.ts +105 -0
- package/src/subtitles/Subtitles.ts +478 -0
- package/src/synthesis/AwsPollyTTS.ts +78 -0
- package/src/synthesis/AzureCognitiveServicesTTS.ts +146 -0
- package/src/synthesis/CoquiServerTTS.ts +29 -0
- package/src/synthesis/ElevenLabsTTS.ts +104 -0
- package/src/synthesis/EspeakTTS.ts +552 -0
- package/src/synthesis/FliteTTS.ts +387 -0
- package/src/synthesis/GoogleCloudTTS.ts +112 -0
- package/src/synthesis/GoogleTranslateTTS.ts +210 -0
- package/src/synthesis/MicrosoftEdgeTTS.ts +298 -0
- package/src/synthesis/SamTTS.ts +30 -0
- package/src/synthesis/SapiTTS.ts +222 -0
- package/src/synthesis/StreamlabsPollyTTS.ts +114 -0
- package/src/synthesis/SvoxPicoTTS.ts +318 -0
- package/src/synthesis/VitsTTS.ts +734 -0
- package/src/tests/Test.ts +24 -0
- package/src/text-language-detection/FastTextLanguageDetection.ts +53 -0
- package/src/text-language-detection/TinyLDLanguageDetection.ts +16 -0
- package/src/typings/Fillers.d.ts +41 -0
- package/src/utilities/BinaryArrayConversion.ts +159 -0
- package/src/utilities/Compression.ts +91 -0
- package/src/utilities/FileDownloader.ts +201 -0
- package/src/utilities/FileSystem.ts +265 -0
- package/src/utilities/Hashing.ts +230 -0
- package/src/utilities/Locale.ts +119 -0
- package/src/utilities/Logger.ts +72 -0
- package/src/utilities/NdArrayUtilities.ts +31 -0
- package/src/utilities/ObjectUtilities.ts +169 -0
- package/src/utilities/OpenPromise.ts +13 -0
- package/src/utilities/PackageManager.ts +97 -0
- package/src/utilities/Queue.ts +17 -0
- package/src/utilities/RandomGenerator.ts +237 -0
- package/src/utilities/SignalChannel.ts +22 -0
- package/src/utilities/TarballMaker.ts +68 -0
- package/src/utilities/Timeline.ts +231 -0
- package/src/utilities/Timer.ts +93 -0
- package/src/utilities/Utilities.ts +574 -0
- package/src/utilities/WasmMemoryManager.ts +516 -0
- package/src/utilities/WebReader.ts +55 -0
- package/src/utilities/WikipediaReader.ts +41 -0
- package/src/voice-activity-detection/SileroVAD.ts +86 -0
- package/src/voice-activity-detection/WebRtcVAD.ts +76 -0
|
@@ -0,0 +1,812 @@
|
|
|
1
|
+
import createMedianFilter from 'moving-median'
|
|
2
|
+
|
|
3
|
+
export function covarianceMatrixOfSamples(samples: number[][], weights?: number[], biased = false) {
|
|
4
|
+
if (samples.length == 0) {
|
|
5
|
+
throw new Error("No vectors given")
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { centeredVectors: centeredSamples, mean } = centerVectors(samples, weights)
|
|
9
|
+
|
|
10
|
+
let covarianceMatrix
|
|
11
|
+
|
|
12
|
+
if (weights) {
|
|
13
|
+
covarianceMatrix = weightedCovarianceMatrixOfCenteredSamples(centeredSamples, weights)
|
|
14
|
+
} else {
|
|
15
|
+
covarianceMatrix = covarianceMatrixOfCenteredSamples(centeredSamples, biased)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return { covarianceMatrix, mean }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function covarianceMatrixOfCenteredSamples(centeredSamples: number[][], biased = false, diagonalRegularizationAmount = 1e-6) {
|
|
22
|
+
const sampleCount = centeredSamples.length
|
|
23
|
+
|
|
24
|
+
if (sampleCount == 0) {
|
|
25
|
+
throw new Error("No vectors given")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const sampleSizeMetric = biased || sampleCount == 1 ? sampleCount : sampleCount - 1
|
|
29
|
+
const featureCount = centeredSamples[0].length
|
|
30
|
+
|
|
31
|
+
const covarianceMatrix = createVectorArray(featureCount, featureCount)
|
|
32
|
+
|
|
33
|
+
if (sampleCount == 1) {
|
|
34
|
+
return covarianceMatrix
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < featureCount; i++) {
|
|
38
|
+
for (let j = 0; j < featureCount; j++) {
|
|
39
|
+
if (i > j) {
|
|
40
|
+
covarianceMatrix[i][j] = covarianceMatrix[j][i]
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let matrixElement = 0.0
|
|
45
|
+
|
|
46
|
+
for (const sample of centeredSamples) {
|
|
47
|
+
matrixElement += sample[i] * sample[j]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
matrixElement /= sampleSizeMetric
|
|
51
|
+
|
|
52
|
+
if (i == j) {
|
|
53
|
+
matrixElement += diagonalRegularizationAmount
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
covarianceMatrix[i][j] = matrixElement
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return covarianceMatrix
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function weightedCovarianceMatrixOfCenteredSamples(centeredSamples: number[][], weights: number[], diagonalRegularizationAmount = 1e-6) {
|
|
64
|
+
const sampleCount = centeredSamples.length
|
|
65
|
+
|
|
66
|
+
if (sampleCount == 0) {
|
|
67
|
+
throw new Error("No vectors given")
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const featureCount = centeredSamples[0].length
|
|
71
|
+
|
|
72
|
+
const covarianceMatrix = createVectorArray(featureCount, featureCount)
|
|
73
|
+
|
|
74
|
+
if (sampleCount == 1) {
|
|
75
|
+
return covarianceMatrix
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < featureCount; i++) {
|
|
79
|
+
for (let j = 0; j < featureCount; j++) {
|
|
80
|
+
if (i > j) {
|
|
81
|
+
covarianceMatrix[i][j] = covarianceMatrix[j][i]
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let matrixElement = 0.0
|
|
86
|
+
|
|
87
|
+
for (let sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) {
|
|
88
|
+
const sample = centeredSamples[sampleIndex]
|
|
89
|
+
const weight = weights[sampleIndex]
|
|
90
|
+
|
|
91
|
+
matrixElement += weight * (sample[i] * sample[j])
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (i == j) {
|
|
95
|
+
matrixElement += diagonalRegularizationAmount
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
covarianceMatrix[i][j] = matrixElement
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return covarianceMatrix
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function centerVectors(vectors: number[][], weights?: number[]) {
|
|
106
|
+
const vectorCount = vectors.length
|
|
107
|
+
|
|
108
|
+
if (vectorCount == 0) {
|
|
109
|
+
return { centeredVectors: [], mean: [] }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let mean: number[]
|
|
113
|
+
if (weights) {
|
|
114
|
+
mean = weightedMeanOfVectors(vectors, weights)
|
|
115
|
+
} else {
|
|
116
|
+
mean = meanOfVectors(vectors)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const centeredVectors: number[][] = new Array(vectorCount)
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < vectorCount; i++) {
|
|
122
|
+
centeredVectors[i] = subtractVectors(vectors[i], mean)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { centeredVectors, mean }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function centerVector(vector: number[]) {
|
|
129
|
+
const mean = meanOfVector(vector)
|
|
130
|
+
|
|
131
|
+
const centeredVector: number[] = new Array(vector.length)
|
|
132
|
+
|
|
133
|
+
for (let i = 0; i < vector.length; i++) {
|
|
134
|
+
centeredVector[i] = vector[i] - mean
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return centeredVector
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function scaleToSumTo1(vector: number[]) {
|
|
141
|
+
if (vector.length == 0) {
|
|
142
|
+
return []
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (vector.length == 1) {
|
|
146
|
+
return [1]
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const minValue = vector[indexOfMin(vector)]
|
|
150
|
+
|
|
151
|
+
const scaledVector = vector.slice()
|
|
152
|
+
|
|
153
|
+
if (minValue < 0) {
|
|
154
|
+
const addedOffset = -minValue * 2
|
|
155
|
+
|
|
156
|
+
for (let i = 0; i < scaledVector.length; i++) {
|
|
157
|
+
scaledVector[i] += addedOffset
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const sum = sumVector(scaledVector)
|
|
162
|
+
|
|
163
|
+
if (sum == 0) {
|
|
164
|
+
return scaledVector
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (sum == Infinity) {
|
|
168
|
+
throw new Error("Vector sum is infinite")
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (let i = 0; i < vector.length; i++) {
|
|
172
|
+
scaledVector[i] /= sum
|
|
173
|
+
|
|
174
|
+
scaledVector[i] = zeroIfNaN(scaledVector[i])
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return scaledVector
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function normalizeVector(vector: number[], kind: "population" | "sample" = "population") {
|
|
181
|
+
if (vector.length == 0) {
|
|
182
|
+
throw new Error("Vector is empty")
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const mean = meanOfVector(vector)
|
|
186
|
+
const stdDeviation = stdDeviationOfVector(vector, kind, mean)
|
|
187
|
+
|
|
188
|
+
const normalizedVector = createVector(vector.length)
|
|
189
|
+
|
|
190
|
+
for (let i = 0; i < vector.length; i++) {
|
|
191
|
+
normalizedVector[i] = (vector[i] - mean) / stdDeviation
|
|
192
|
+
|
|
193
|
+
normalizedVector[i] = zeroIfNaN(normalizedVector[i])
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return { normalizedVector, mean, stdDeviation }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function normalizeVectors(vectors: number[][], kind: "population" | "sample" = "population") {
|
|
200
|
+
const vectorCount = vectors.length
|
|
201
|
+
|
|
202
|
+
if (vectorCount == 0) {
|
|
203
|
+
return { normalizedVectors: [], mean: [], stdDeviation: [] }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const featureCount = vectors[0].length
|
|
207
|
+
|
|
208
|
+
const mean = meanOfVectors(vectors)
|
|
209
|
+
const stdDeviation = stdDeviationOfVectors(vectors, kind, mean)
|
|
210
|
+
|
|
211
|
+
const normalizedVectors: number[][] = []
|
|
212
|
+
|
|
213
|
+
for (const vector of vectors) {
|
|
214
|
+
const normalizedVector = createVector(featureCount)
|
|
215
|
+
|
|
216
|
+
for (let featureIndex = 0; featureIndex < featureCount; featureIndex++) {
|
|
217
|
+
normalizedVector[featureIndex] = (vector[featureIndex] - mean[featureIndex]) / stdDeviation[featureIndex]
|
|
218
|
+
|
|
219
|
+
normalizedVector[featureIndex] = zeroIfNaN(normalizedVector[featureIndex])
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
normalizedVectors.push(normalizedVector)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return { normalizedVectors, mean, stdDeviation }
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function deNormalizeVectors(normalizedVectors: number[][], originalMean: number[], originalStdDeviation: number[]) {
|
|
229
|
+
const vectorCount = normalizeVectors.length
|
|
230
|
+
|
|
231
|
+
if (vectorCount == 0) {
|
|
232
|
+
return []
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const featureCount = normalizedVectors[0].length
|
|
236
|
+
|
|
237
|
+
const deNormalizedVectors: number[][] = []
|
|
238
|
+
|
|
239
|
+
for (const normalizedVector of normalizedVectors) {
|
|
240
|
+
const deNormalizedVector = createVector(featureCount)
|
|
241
|
+
|
|
242
|
+
for (let featureIndex = 0; featureIndex < featureCount; featureIndex++) {
|
|
243
|
+
deNormalizedVector[featureIndex] = originalMean[featureIndex] + (normalizedVector[featureIndex] * originalStdDeviation[featureIndex])
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
deNormalizedVectors.push(deNormalizedVector)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return deNormalizedVectors
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function meanOfVectors(vectors: number[][]) {
|
|
253
|
+
const vectorCount = vectors.length
|
|
254
|
+
|
|
255
|
+
if (vectorCount == 0) {
|
|
256
|
+
return []
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const featureCount = vectors[0].length
|
|
260
|
+
|
|
261
|
+
const result = createVector(featureCount)
|
|
262
|
+
|
|
263
|
+
for (const vector of vectors) {
|
|
264
|
+
for (let featureIndex = 0; featureIndex < featureCount; featureIndex++) {
|
|
265
|
+
result[featureIndex] += vector[featureIndex]
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
for (let featureIndex = 0; featureIndex < featureCount; featureIndex++) {
|
|
270
|
+
result[featureIndex] /= vectorCount
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return result
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function weightedMeanOfVectors(vectors: number[][], weights: number[]) {
|
|
277
|
+
const vectorCount = vectors.length
|
|
278
|
+
|
|
279
|
+
if (vectorCount == 0) {
|
|
280
|
+
return []
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const featureCount = vectors[0].length
|
|
284
|
+
|
|
285
|
+
const result = createVector(featureCount)
|
|
286
|
+
|
|
287
|
+
for (let vectorIndex = 0; vectorIndex < vectorCount; vectorIndex++) {
|
|
288
|
+
const vector = vectors[vectorIndex]
|
|
289
|
+
const vectorWeight = weights[vectorIndex]
|
|
290
|
+
|
|
291
|
+
for (let featureIndex = 0; featureIndex < featureCount; featureIndex++) {
|
|
292
|
+
result[featureIndex] += vectorWeight * vector[featureIndex]
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return result
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function stdDeviationOfVectors(vectors: number[][], kind: "population" | "sample" = "population", mean?: number[]) {
|
|
300
|
+
return varianceOfVectors(vectors, kind, mean).map(v => Math.sqrt(v))
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function varianceOfVectors(vectors: number[][], kind: "population" | "sample" = "population", mean?: number[]) {
|
|
304
|
+
const vectorCount = vectors.length
|
|
305
|
+
|
|
306
|
+
if (vectorCount == 0) {
|
|
307
|
+
return []
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const sampleSizeMetric = kind == "population" || vectorCount == 1 ? vectorCount : vectorCount - 1
|
|
311
|
+
const featureCount = vectors[0].length
|
|
312
|
+
|
|
313
|
+
if (!mean) {
|
|
314
|
+
mean = meanOfVectors(vectors)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const result = createVector(featureCount)
|
|
318
|
+
|
|
319
|
+
for (const vector of vectors) {
|
|
320
|
+
for (let i = 0; i < featureCount; i++) {
|
|
321
|
+
result[i] += (vector[i] - mean[i]) ** 2
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
for (let i = 0; i < featureCount; i++) {
|
|
326
|
+
result[i] /= sampleSizeMetric
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return result
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function meanOfVector(vector: number[]) {
|
|
333
|
+
if (vector.length == 0) {
|
|
334
|
+
throw new Error("Vector is empty")
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return sumVector(vector) / vector.length
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function medianOfVector(vector: number[]) {
|
|
341
|
+
if (vector.length == 0) {
|
|
342
|
+
throw new Error("Vector is empty")
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return vector[Math.floor(vector.length / 2)]
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export function stdDeviationOfVector(vector: number[], kind: "population" | "sample" = "population", mean?: number) {
|
|
349
|
+
return Math.sqrt(varianceOfVector(vector, kind, mean))
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function varianceOfVector(vector: number[], kind: "population" | "sample" = "population", mean?: number) {
|
|
353
|
+
if (vector.length == 0) {
|
|
354
|
+
throw new Error("Vector is empty")
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const sampleSizeMetric = kind == "population" || vector.length == 1 ? vector.length : vector.length - 1
|
|
358
|
+
|
|
359
|
+
if (mean == null) {
|
|
360
|
+
mean = meanOfVector(vector)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
let result = 0.0
|
|
364
|
+
|
|
365
|
+
for (const value of vector) {
|
|
366
|
+
result += (value - mean) ** 2
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return result / sampleSizeMetric
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export function logOfVector(vector: number[], minVal = 1e-40) {
|
|
373
|
+
return vector.map(value => Math.log(minVal + value))
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export function expOfVector(vector: number[]) {
|
|
377
|
+
return vector.map(value => Math.exp(value))
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export function transpose(matrix: number[][]) {
|
|
381
|
+
const vectorCount = matrix.length
|
|
382
|
+
const featureCount = matrix[0].length
|
|
383
|
+
|
|
384
|
+
const transposedMatrix = createVectorArray(featureCount, vectorCount)
|
|
385
|
+
|
|
386
|
+
for (let i = 0; i < vectorCount; i++) {
|
|
387
|
+
for (let j = 0; j < featureCount; j++) {
|
|
388
|
+
transposedMatrix[j][i] = matrix[i][j]
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return transposedMatrix
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export function movingAverageOfWindow3(vector: number[]) {
|
|
396
|
+
const elementCount = vector.length
|
|
397
|
+
|
|
398
|
+
if (elementCount == 0) {
|
|
399
|
+
return []
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (elementCount == 1) {
|
|
403
|
+
return vector.slice()
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const result: number[] = []
|
|
407
|
+
|
|
408
|
+
result.push((vector[0] + vector[0] + vector[1]) / 3)
|
|
409
|
+
|
|
410
|
+
for (let i = 1; i < elementCount - 1; i++) {
|
|
411
|
+
result.push((vector[i - 1] + vector[i] + vector[i + 1]) / 3)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
result.push((vector[elementCount - 2] + vector[elementCount - 1] + vector[elementCount - 1]) / 3)
|
|
415
|
+
|
|
416
|
+
return result
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export function averageMeanSquaredError(actual: number[][], expected: number[][]) {
|
|
420
|
+
if (actual.length != expected.length) {
|
|
421
|
+
throw new Error("Vectors are not the same length")
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const vectorCount = actual.length
|
|
425
|
+
|
|
426
|
+
if (vectorCount == 0) {
|
|
427
|
+
return 0
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
let sum = 0.0
|
|
431
|
+
|
|
432
|
+
for (let i = 0; i < vectorCount; i++) {
|
|
433
|
+
sum += meanSquaredError(actual[i], expected[i])
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return sum / vectorCount
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export function meanSquaredError(actual: number[], expected: number[]) {
|
|
440
|
+
if (actual.length != expected.length) {
|
|
441
|
+
throw new Error("Vectors are not the same length")
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const featureCount = actual.length
|
|
445
|
+
|
|
446
|
+
if (featureCount == 0) {
|
|
447
|
+
return 0
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
let sum = 0.0
|
|
451
|
+
|
|
452
|
+
for (let i = 0; i < featureCount; i++) {
|
|
453
|
+
sum += (actual[i] - expected[i]) ** 2
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return sum / featureCount
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export function eucledianDistance(vector1: number[], vector2: number[]) {
|
|
460
|
+
return Math.sqrt(squaredEucledianDistance(vector1, vector2))
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export function squaredEucledianDistance(vector1: number[], vector2: number[]) {
|
|
464
|
+
if (vector1.length != vector2.length) {
|
|
465
|
+
throw new Error("Vectors are not the same length")
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const elementCount = vector1.length
|
|
469
|
+
|
|
470
|
+
if (elementCount == 0) {
|
|
471
|
+
return 0
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
let sum = 0.0
|
|
475
|
+
|
|
476
|
+
for (let i = 0; i < elementCount; i++) {
|
|
477
|
+
sum += (vector1[i] - vector2[i]) ** 2
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return sum
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export function cosineDistance(vector1: number[], vector2: number[]) {
|
|
484
|
+
return 1 - cosineSimilarity(vector1, vector2)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export function cosineSimilarity(vector1: number[], vector2: number[]) {
|
|
488
|
+
if (vector1.length != vector2.length) {
|
|
489
|
+
throw new Error("Vectors are not the same length")
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (vector1.length == 0) {
|
|
493
|
+
return 0
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const elementCount = vector1.length
|
|
497
|
+
|
|
498
|
+
let dotProduct = 0.0
|
|
499
|
+
|
|
500
|
+
let squaredMagnitude1 = 0.0
|
|
501
|
+
let squaredMagnitude2 = 0.0
|
|
502
|
+
|
|
503
|
+
for (let i = 0; i < elementCount; i++) {
|
|
504
|
+
dotProduct += vector1[i] * vector2[i]
|
|
505
|
+
|
|
506
|
+
squaredMagnitude1 += vector1[i] ** 2
|
|
507
|
+
squaredMagnitude2 += vector2[i] ** 2
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const result = dotProduct / (Math.sqrt(squaredMagnitude1) * Math.sqrt(squaredMagnitude2))
|
|
511
|
+
|
|
512
|
+
return zeroIfNaN(result)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export function minkowskiDistance(vector1: number[], vector2: number[], power: number) {
|
|
516
|
+
if (vector1.length != vector2.length) {
|
|
517
|
+
throw new Error("Vectors are not the same length")
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const elementCount = vector1.length
|
|
521
|
+
|
|
522
|
+
if (elementCount == 0) {
|
|
523
|
+
return 0
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
let sum = 0.0
|
|
527
|
+
|
|
528
|
+
for (let i = 0; i < elementCount; i++) {
|
|
529
|
+
sum += Math.abs(vector1[i] - vector2[i]) ** power
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return sum ** (1 / power)
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export function cosineDistancePrecomputedMagnitudes(vector1: number[], vector2: number[], magnitude1: number, magnitude2: number) {
|
|
536
|
+
return 1 - cosineSimilarityPrecomputedMagnitudes(vector1, vector2, magnitude1, magnitude2)
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export function cosineSimilarityPrecomputedMagnitudes(vector1: number[], vector2: number[], magnitude1: number, magnitude2: number) {
|
|
540
|
+
if (vector1.length != vector2.length) {
|
|
541
|
+
throw new Error("Vectors are not the same length")
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (vector1.length == 0) {
|
|
545
|
+
return 0
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const featureCount = vector1.length
|
|
549
|
+
|
|
550
|
+
let dotProduct = 0.0
|
|
551
|
+
|
|
552
|
+
for (let i = 0; i < featureCount; i++) {
|
|
553
|
+
dotProduct += vector1[i] * vector2[i]
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const result = dotProduct / (magnitude1 * magnitude2)
|
|
557
|
+
|
|
558
|
+
return zeroIfNaN(result)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
export function subtractVectors(vector1: number[], vector2: number[]) {
|
|
563
|
+
if (vector1.length != vector2.length) {
|
|
564
|
+
throw new Error("Vectors are not the same length")
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const result = createVector(vector1.length)
|
|
568
|
+
|
|
569
|
+
for (let i = 0; i < vector1.length; i++) {
|
|
570
|
+
result[i] = vector1[i] - vector2[i]
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return result
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export function sumVector(vector: number[]) {
|
|
577
|
+
let result = 0.0
|
|
578
|
+
|
|
579
|
+
for (let i = 0; i < vector.length; i++) {
|
|
580
|
+
result += vector[i]
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
return result
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
export function dotProduct(vector1: number[], vector2: number[]) {
|
|
587
|
+
if (vector1.length != vector2.length) {
|
|
588
|
+
throw new Error("Vectors are not the same length")
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const elementCount = vector1.length
|
|
592
|
+
|
|
593
|
+
let result = 0.0
|
|
594
|
+
|
|
595
|
+
for (let i = 0; i < elementCount; i++) {
|
|
596
|
+
result += vector1[i] * vector2[i]
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return result
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
export function magnitude(vector: number[]) {
|
|
603
|
+
const featureCount = vector.length
|
|
604
|
+
|
|
605
|
+
let squaredMagnitude = 0.0
|
|
606
|
+
|
|
607
|
+
for (let i = 0; i < featureCount; i++) {
|
|
608
|
+
squaredMagnitude += vector[i] ** 2
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
return Math.sqrt(squaredMagnitude)
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export function maxValue(vector: number[]) {
|
|
615
|
+
return vector[indexOfMax(vector)]
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
export function indexOfMax(vector: number[]) {
|
|
619
|
+
let maxValue = -Infinity
|
|
620
|
+
let result = -1
|
|
621
|
+
|
|
622
|
+
for (let i = 0; i < vector.length; i++) {
|
|
623
|
+
if (vector[i] > maxValue) {
|
|
624
|
+
maxValue = vector[i]
|
|
625
|
+
result = i
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
return result
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export function minValue(vector: number[]) {
|
|
633
|
+
return vector[indexOfMin(vector)]
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export function indexOfMin(vector: number[]) {
|
|
637
|
+
let minValue = Infinity
|
|
638
|
+
let result = -1
|
|
639
|
+
|
|
640
|
+
for (let i = 0; i < vector.length; i++) {
|
|
641
|
+
if (vector[i] < minValue) {
|
|
642
|
+
minValue = vector[i]
|
|
643
|
+
result = i
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
return result
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
export function exponentialSmoothingMeanOfVectors(vectors: number[][], smoothingFactor: number) {
|
|
651
|
+
const vectorCount = vectors.length
|
|
652
|
+
|
|
653
|
+
if (vectorCount == 0) {
|
|
654
|
+
return []
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const featureCount = vectors[0].length
|
|
658
|
+
|
|
659
|
+
const currentEstimate = createVector(featureCount)
|
|
660
|
+
|
|
661
|
+
for (let i = 0; i < vectorCount; i++) {
|
|
662
|
+
for (let j = 0; j < featureCount; j++) {
|
|
663
|
+
const value = vectors[i][j]
|
|
664
|
+
|
|
665
|
+
currentEstimate[j] = (smoothingFactor * value) + ((1 - smoothingFactor) * currentEstimate[j])
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
return currentEstimate
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export function sigmoid(x: number) {
|
|
673
|
+
const result = 1 / (1 + Math.exp(-x))
|
|
674
|
+
|
|
675
|
+
return zeroIfNaN(result)
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
export function softmax(logits: number[], temperature = 1.0) {
|
|
679
|
+
if (logits.length == 0) {
|
|
680
|
+
return []
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
let maxValue = -Infinity
|
|
684
|
+
|
|
685
|
+
for (const val of logits) {
|
|
686
|
+
if (val > maxValue) {
|
|
687
|
+
maxValue = val
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const temperatureMultiplier = 1 / temperature
|
|
692
|
+
|
|
693
|
+
const result: number[] = []
|
|
694
|
+
|
|
695
|
+
let sumOfExponentiatedValues = 0.0
|
|
696
|
+
|
|
697
|
+
for (const value of logits) {
|
|
698
|
+
const eToValue = Math.exp((value - maxValue) * temperatureMultiplier)
|
|
699
|
+
|
|
700
|
+
sumOfExponentiatedValues += eToValue
|
|
701
|
+
|
|
702
|
+
result.push(eToValue)
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const sumOfExponentiatedValuesMultiplier = 1 / (sumOfExponentiatedValues + 1e-40)
|
|
706
|
+
|
|
707
|
+
for (let i = 0; i < result.length; i++) {
|
|
708
|
+
result[i] *= sumOfExponentiatedValuesMultiplier
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
return result
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
export function hammingDistance(value1: number, value2: number, bitLength = 32) {
|
|
715
|
+
let valueXor = value1 ^ value2
|
|
716
|
+
|
|
717
|
+
let result = 0
|
|
718
|
+
|
|
719
|
+
for (let i = 0; i < bitLength; i++) {
|
|
720
|
+
result += valueXor & 1
|
|
721
|
+
valueXor = valueXor >> 1
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return result
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export function medianFilter(vector: number[], width: number) {
|
|
728
|
+
const filter = createMedianFilter(width)
|
|
729
|
+
const result = []
|
|
730
|
+
|
|
731
|
+
for (let i = 0; i < vector.length; i++) {
|
|
732
|
+
result.push(filter(vector[i]))
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
return result
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
export function createVectorArray(vectorCount: number, featureCount: number, initialValue = 0.0) {
|
|
739
|
+
const result: number[][] = new Array(vectorCount)
|
|
740
|
+
|
|
741
|
+
for (let i = 0; i < vectorCount; i++) {
|
|
742
|
+
result[i] = createVector(featureCount, initialValue)
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
return result
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
export function createVector(elementCount: number, initialValue = 0.0) {
|
|
749
|
+
const result: number[] = new Array(elementCount)
|
|
750
|
+
|
|
751
|
+
for (let i = 0; i < elementCount; i++) {
|
|
752
|
+
result[i] = initialValue
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
return result
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
export function createVectorForIntegerRange(start: number, end: number) {
|
|
759
|
+
const newVector: number[] = []
|
|
760
|
+
|
|
761
|
+
for (let i = start; i < end; i++) {
|
|
762
|
+
newVector.push(i)
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return newVector
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
export function zeroIfNaN(val: number) {
|
|
769
|
+
if (isNaN(val)) {
|
|
770
|
+
return 0
|
|
771
|
+
} else {
|
|
772
|
+
return val
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
export function logSumExp(values: number[], minVal = 1e-40) {
|
|
777
|
+
return Math.log(minVal + sumExp(values))
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
export function sumExp(values: number[]) {
|
|
781
|
+
let sumOfExp = 0
|
|
782
|
+
|
|
783
|
+
for (const value of values) {
|
|
784
|
+
sumOfExp += Math.exp(value)
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
return sumOfExp
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
export function logSoftmax(values: number[], minVal = 1e-40) {
|
|
791
|
+
const softMaxOfValues = softmax(values)
|
|
792
|
+
return logOfVector(softMaxOfValues, minVal)
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
export class IncrementalMean {
|
|
796
|
+
currentElementCount = 0
|
|
797
|
+
currentMean = 0.0
|
|
798
|
+
|
|
799
|
+
addValueToMean(value: number) {
|
|
800
|
+
this.currentElementCount += 1
|
|
801
|
+
this.currentMean += (value + this.currentMean) / this.currentElementCount
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// 1, 3.2, 7.23
|
|
805
|
+
// 0 + ((1 - 0) / 1) = 1
|
|
806
|
+
// 1 + ((3.2 - 1) / 2) = 2.1
|
|
807
|
+
// 2.1 + ((7.23 - 3.1) / 3) = 2.04
|
|
808
|
+
|
|
809
|
+
// 3.81
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
export type DistanceFunction = (a: number[], b: number[]) => number
|