@mineproness/tensorloop 2.0.0 → 2.1.11
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/package.json +1 -1
- package/readme.md +4 -3
- package/src/Embedding/index.d.ts +1 -1
- package/src/Embedding/index.js +13 -19
- package/src/FFN/index.js +14 -18
- package/src/GELU/index.d.ts +2 -2
- package/src/GELU/index.js +19 -29
- package/src/Linear/index.d.ts +2 -2
- package/src/Linear/index.js +12 -14
- package/src/PositionEmbedding/index.d.ts +1 -1
- package/src/PositionEmbedding/index.js +5 -3
- package/src/ReLU/index.d.ts +1 -0
- package/src/ReLU/index.js +12 -9
- package/src/SelfAttention/index.js +17 -84
- package/src/Softmax/index.d.ts +0 -1
- package/src/Softmax/index.js +9 -11
- package/src/TransformerBlock/index.d.ts +2 -1
- package/src/TransformerBlock/index.js +3 -1
- package/src/gpiInit.js +721 -0
- package/src/GPU.js +0 -279
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -9,15 +9,16 @@ A high-performance JavaScript library that provides essential AI and Large Langu
|
|
|
9
9
|
- **Transformer Block**: Complete modular block managing full attention and forward/backward training passes.
|
|
10
10
|
- **Embedding Vectors**: High-speed lookup and embedding initialization.
|
|
11
11
|
- **Linear Layer**: Fully connected layers with manageable weights and biases.
|
|
12
|
-
- **Activations**: Forward and backward propagation for **Softmax**, **ReLU**,
|
|
12
|
+
- **Activations**: Forward and backward propagation for **Softmax**, **ReLU**, **GELU**.
|
|
13
13
|
- **Loss Functions**: **CrossEntropy** loss calculation for training classification tasks.
|
|
14
14
|
- **Attention & Positioning**: Built-in **Self-Attention** and **Positional Embedding** matrices.
|
|
15
15
|
- **Text Processing**: Built-in **Tokenizer** to convert raw text into token IDs and back.
|
|
16
16
|
- **Special Tokens**: Native support for `<PAD>` and `<EOS>`.
|
|
17
17
|
- **FFN BLOCK**: It add a layer to understand Complex Patterns.
|
|
18
|
-
-
|
|
18
|
+
- **GPU SUPPORT**: Now, The tensorloop can Do Math with GPU.
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
|
|
21
22
|
## 🏗 Core Architecture
|
|
22
23
|
|
|
23
24
|
### Transformer Block
|
|
@@ -54,7 +55,7 @@ You can configure saving mechanisms by passing a configuration object to the `Em
|
|
|
54
55
|
import { Embedding, Linear } from '@mineproness/tensorloop'
|
|
55
56
|
|
|
56
57
|
// Initialize an Embedding layer and auto-save the weights
|
|
57
|
-
const embedding = new Embedding(1024, 2000, {
|
|
58
|
+
const embedding = new Embedding(1024, 2000, 16 {
|
|
58
59
|
save: {
|
|
59
60
|
filename: "./model/vectors.bin"
|
|
60
61
|
}
|
package/src/Embedding/index.d.ts
CHANGED
package/src/Embedding/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs, { existsSync } from 'fs'
|
|
2
2
|
import { SaveVectors, LoadVectors } from '../GetConfigs.js'
|
|
3
|
+
import { GPUEmbedding } from '../gpiInit.js'
|
|
3
4
|
// import { GPUEmbedding } from '../GPU.js'
|
|
4
5
|
// import { config } from 'process'
|
|
5
6
|
|
|
@@ -18,8 +19,8 @@ export class Embedding {
|
|
|
18
19
|
vectors = []
|
|
19
20
|
configs;
|
|
20
21
|
embeddingSize = 0
|
|
21
|
-
|
|
22
|
-
constructor(embeddingSize, vocabSize, configs) {
|
|
22
|
+
gpu;
|
|
23
|
+
constructor(embeddingSize, vocabSize, contextSize, configs) {
|
|
23
24
|
this.configs = configs
|
|
24
25
|
this.embeddingSize = embeddingSize
|
|
25
26
|
if (configs && configs.save) {
|
|
@@ -33,27 +34,20 @@ export class Embedding {
|
|
|
33
34
|
this.vectors = GenerateVectors(embeddingSize, vocabSize)
|
|
34
35
|
|
|
35
36
|
}
|
|
37
|
+
this.gpu = new GPUEmbedding(this.vectors, vocabSize, embeddingSize, contextSize)
|
|
36
38
|
}
|
|
37
39
|
forward(token) {
|
|
38
|
-
|
|
39
|
-
return token.map((e) => {
|
|
40
|
-
return this.vectors[e]
|
|
41
|
-
})
|
|
42
|
-
} else {
|
|
43
|
-
return this.vectors[token]
|
|
44
|
-
}
|
|
40
|
+
return this.gpu.forward(token)
|
|
45
41
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.vectors[token][a] -= learingRate * inputGradient[a]
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
backward(tokens, inputGradient, learingRate){
|
|
52
|
-
for(let a = 0; a < inputGradient.length; a++){
|
|
53
|
-
this.backwards(tokens[a], inputGradient[a], learingRate)
|
|
54
|
-
}
|
|
42
|
+
backward(inputGradient, learingRate){
|
|
43
|
+
this.gpu.backward(inputGradient, learingRate)
|
|
55
44
|
}
|
|
56
45
|
Save() {
|
|
57
|
-
|
|
46
|
+
const vectors = []
|
|
47
|
+
for(let i = 0; i < this.gpu.vectors.length; i++){
|
|
48
|
+
const out = this.gpu.vectors[i].toArray()
|
|
49
|
+
vectors.push(...out)
|
|
50
|
+
}
|
|
51
|
+
SaveVectors(vectors.map((e)=> new Float32Array(e)), this.configs.save.filename)
|
|
58
52
|
}
|
|
59
53
|
}
|
package/src/FFN/index.js
CHANGED
|
@@ -2,12 +2,15 @@ import { Linear } from '../Linear/index.js'
|
|
|
2
2
|
import { GELU } from '../GELU/index.js'
|
|
3
3
|
import { ReLU } from '../ReLU/index.js'
|
|
4
4
|
import { join } from 'path'
|
|
5
|
+
import { GPUHiddenLayer } from '../gpiInit.js';
|
|
5
6
|
export class FFN {
|
|
6
7
|
linear1;
|
|
7
8
|
linear2;
|
|
8
9
|
hidden;
|
|
10
|
+
hiddenName;
|
|
9
11
|
constructor(embeddingSize, hiddenLayer = "gelu", configs) {
|
|
10
|
-
this.
|
|
12
|
+
this.hiddenName = hiddenLayer
|
|
13
|
+
this.hidden = hiddenLayer.toLocaleLowerCase() == "gelu" ? new GELU() : new GPUHiddenLayer()
|
|
11
14
|
if (configs) {
|
|
12
15
|
this.linear1 = new Linear(embeddingSize, 4 * embeddingSize, {
|
|
13
16
|
save: {
|
|
@@ -24,32 +27,25 @@ export class FFN {
|
|
|
24
27
|
this.linear2 = new Linear(4 * embeddingSize, embeddingSize)
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
|
-
forward(input){
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const hidden = this.hidden.forward(out1, a)
|
|
32
|
-
result[a] = this.linear2.forward(hidden)
|
|
33
|
-
}
|
|
30
|
+
forward(input) {
|
|
31
|
+
const out1 = this.linear1.forward(input)
|
|
32
|
+
let hidden = this.hidden.forward(out1)
|
|
33
|
+
const result = this.linear2.forward(hidden)
|
|
34
34
|
return result
|
|
35
35
|
}
|
|
36
|
-
backward(dInput, LearningRate){
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const dHidden = this.hidden.backward(out2, a)
|
|
41
|
-
result[a] = this.linear1.backward(dHidden, LearningRate, a)
|
|
42
|
-
}
|
|
36
|
+
backward(dInput, LearningRate) {
|
|
37
|
+
const out2 = this.linear2.backward(dInput, LearningRate);
|
|
38
|
+
const dHidden = this.hidden.backward(out2)
|
|
39
|
+
const result = this.linear1.backward(dHidden, LearningRate)
|
|
43
40
|
return result
|
|
44
41
|
}
|
|
45
|
-
Save(){
|
|
42
|
+
Save() {
|
|
46
43
|
this.linear1.Save()
|
|
47
44
|
this.linear2.Save()
|
|
48
45
|
}
|
|
49
|
-
ClearInputCache(){
|
|
46
|
+
ClearInputCache() {
|
|
50
47
|
this.linear1.ClearInputCache()
|
|
51
48
|
this.linear2.ClearInputCache()
|
|
52
49
|
this.hidden.ClearInputCache()
|
|
53
|
-
|
|
54
50
|
}
|
|
55
51
|
}
|
package/src/GELU/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export class GELU{
|
|
2
2
|
input : Float32Array[];
|
|
3
|
-
forward(input: Float32Array
|
|
4
|
-
backward(Doutput: Float32Array
|
|
3
|
+
forward(input: Float32Array[]) : Float32Array[];
|
|
4
|
+
backward(Doutput: Float32Array[]) : Float32Array[];
|
|
5
5
|
ClearInputCache() : void;
|
|
6
6
|
}
|
package/src/GELU/index.js
CHANGED
|
@@ -1,40 +1,30 @@
|
|
|
1
|
+
import { GELUGPU } from "../gpiInit.js";
|
|
2
|
+
|
|
1
3
|
export class GELU {
|
|
4
|
+
gpu;
|
|
5
|
+
inputs = [];
|
|
2
6
|
constructor() {
|
|
3
7
|
this.inputs = []
|
|
8
|
+
|
|
4
9
|
}
|
|
5
10
|
|
|
6
|
-
forward(input
|
|
7
|
-
this.inputs
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
for (let i = 0; i < input.length; i++) {
|
|
11
|
-
const x = input[i]
|
|
12
|
-
const u = k * (x + 0.044715 * x * x * x)
|
|
13
|
-
output[i] = 0.5 * x * (1 + Math.tanh(u))
|
|
11
|
+
forward(input) {
|
|
12
|
+
this.inputs = input
|
|
13
|
+
if(!this.gpu){
|
|
14
|
+
this.gpu = new GELUGPU(input[0].length, input.length)
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
+
// const output = new Float32Array(input.length)
|
|
17
|
+
// const k = Math.sqrt(2 / Math.PI)
|
|
18
|
+
// for (let i = 0; i < input.length; i++) {
|
|
19
|
+
// const x = input[i]
|
|
20
|
+
// const u = k * (x + 0.044715 * x * x * x)
|
|
21
|
+
// output[i] = 0.5 * x * (1 + Math.tanh(u))
|
|
22
|
+
// }
|
|
23
|
+
return this.gpu.forward(input)
|
|
16
24
|
}
|
|
17
25
|
|
|
18
|
-
backward(dOutput
|
|
19
|
-
|
|
20
|
-
if (!input) throw new Error(`No GELU cache for index ${index}`);
|
|
21
|
-
const grad = new Float32Array(dOutput.length)
|
|
22
|
-
const k = Math.sqrt(2 / Math.PI)
|
|
23
|
-
for (let i = 0; i < dOutput.length; i++) {
|
|
24
|
-
const x = input[i]
|
|
25
|
-
const x3 = x * x * x
|
|
26
|
-
const u = k * (x + 0.044715 * x3)
|
|
27
|
-
const t = Math.tanh(u)
|
|
28
|
-
const sech2 = 1 - t * t
|
|
29
|
-
const duDx = k * (1 + 3 * 0.044715 * x * x)
|
|
30
|
-
const geluGrad =
|
|
31
|
-
0.5 * (1 + t) +
|
|
32
|
-
0.5 * x * sech2 * duDx
|
|
33
|
-
|
|
34
|
-
grad[i] = dOutput[i] * geluGrad
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return grad
|
|
26
|
+
backward(dOutput) {
|
|
27
|
+
return this.gpu.backward(dOutput, this.inputs)
|
|
38
28
|
}
|
|
39
29
|
|
|
40
30
|
ClearInputCache() {
|
package/src/Linear/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export class Linear{
|
|
2
2
|
Weights : Float32Array[]
|
|
3
3
|
Bias: Float32Array
|
|
4
|
-
constructor(embeddingSize : number, vocabSize : number,
|
|
4
|
+
constructor(embeddingSize : number, vocabSize : number, configs: {
|
|
5
5
|
save: {
|
|
6
6
|
filename: string[]
|
|
7
7
|
}
|
|
8
8
|
})
|
|
9
9
|
forward(input : Float32Array[]) : Float32Array[]
|
|
10
|
-
backward(outGradient : number[] , learingRate: number
|
|
10
|
+
backward(outGradient : number[] , learingRate: number) : Float32Array[]
|
|
11
11
|
Save() : void
|
|
12
12
|
ClearInputCache() : void
|
|
13
13
|
}
|
package/src/Linear/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LoadBias, LoadVectors, SaveBias, SaveVectors } from '../GetConfigs.js'
|
|
2
2
|
import { existsSync } from 'fs'
|
|
3
|
-
import { GPULinear } from '../
|
|
3
|
+
import { GPULinear } from '../gpiInit.js'
|
|
4
4
|
function GenerateWeightsBias(embeddingSize, vocabSize) {
|
|
5
5
|
const vectors = []
|
|
6
6
|
const Bias = new Float32Array(vocabSize)
|
|
@@ -20,7 +20,7 @@ export class Linear {
|
|
|
20
20
|
configs;
|
|
21
21
|
input = [];
|
|
22
22
|
gpu;
|
|
23
|
-
constructor(embeddingSize, vocabSize,
|
|
23
|
+
constructor(embeddingSize, vocabSize, configs) {
|
|
24
24
|
if (configs && configs.save) {
|
|
25
25
|
this.configs = configs
|
|
26
26
|
if (existsSync(configs.save.filename[0]) && existsSync(configs.save.filename[1])) {
|
|
@@ -40,28 +40,26 @@ export class Linear {
|
|
|
40
40
|
this.Weights = vectors;
|
|
41
41
|
this.Bias = Bias;
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
this.gpu.InitKernel(this.Weights, this.Bias, embeddingSize, contextSize)
|
|
43
|
+
|
|
45
44
|
}
|
|
46
45
|
Save() {
|
|
47
|
-
const {bias, weights} = this.gpu.
|
|
46
|
+
const {bias, weights} = this.gpu.Save()
|
|
48
47
|
SaveVectors(weights, this.configs.save.filename[0])
|
|
49
48
|
SaveBias(bias, this.configs.save.filename[1])
|
|
50
49
|
}
|
|
51
50
|
forward(input) {
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
if (!this.gpu) {
|
|
52
|
+
this.gpu = new GPULinear(this.Weights, this.Bias, input.length)
|
|
53
|
+
}
|
|
54
|
+
for (let a = 0; a < input.length; a++) {
|
|
54
55
|
this.input[a] = input;
|
|
55
|
-
|
|
56
56
|
}
|
|
57
|
-
return this.gpu.
|
|
57
|
+
return this.gpu.forward(input)
|
|
58
58
|
}
|
|
59
|
-
backward(
|
|
60
|
-
|
|
61
|
-
const inputGradient = this.gpu.CalculateBackward(outputGradient, learningRate, input)
|
|
62
|
-
return inputGradient
|
|
59
|
+
backward(out, lr){
|
|
60
|
+
return this.gpu.backward(out, this.input, lr)
|
|
63
61
|
}
|
|
64
|
-
ClearInputCache(){
|
|
62
|
+
ClearInputCache() {
|
|
65
63
|
this.input = []
|
|
66
64
|
}
|
|
67
65
|
}
|
|
@@ -8,5 +8,5 @@ export class PositionEmbedding{
|
|
|
8
8
|
forward(position: number | number[]) : Float32Array[] | Float32Array[][]
|
|
9
9
|
backward(pos: number , inputGradient: number[] | Float32Array[], learingRate: number) : void
|
|
10
10
|
Save() : void;
|
|
11
|
-
addPos(
|
|
11
|
+
addPos(vectors : Float32Array[][]) : Float32Array
|
|
12
12
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs, { existsSync } from 'fs'
|
|
2
2
|
import { LoadVectors, SaveVectors } from '../GetConfigs.js'
|
|
3
3
|
// import { config } from 'process'
|
|
4
|
+
import { GPUEmbedding } from '../gpiInit.js'
|
|
4
5
|
|
|
5
6
|
function GenerateVectors(embeddingSize, vocabSize) {
|
|
6
7
|
const vector = []
|
|
@@ -16,7 +17,8 @@ function GenerateVectors(embeddingSize, vocabSize) {
|
|
|
16
17
|
export class PositionEmbedding {
|
|
17
18
|
vectors = []
|
|
18
19
|
configs;
|
|
19
|
-
embeddingSize = 0
|
|
20
|
+
embeddingSize = 0;
|
|
21
|
+
gpu;
|
|
20
22
|
constructor(embeddingSize, vocabSize, configs) {
|
|
21
23
|
this.configs = configs
|
|
22
24
|
this.embeddingSize = embeddingSize
|
|
@@ -29,7 +31,7 @@ export class PositionEmbedding {
|
|
|
29
31
|
}
|
|
30
32
|
} else {
|
|
31
33
|
this.vectors = GenerateVectors(embeddingSize, vocabSize)
|
|
32
|
-
|
|
34
|
+
this.gpu = new GPUEmbedding(this.vectors, vocabSize, embeddingSize, 1)
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
forward(token) {
|
|
@@ -55,7 +57,7 @@ export class PositionEmbedding {
|
|
|
55
57
|
|
|
56
58
|
for (let pos = 0; pos < xEM.length; pos++) {
|
|
57
59
|
const tokenVector = xEM[pos]
|
|
58
|
-
const posVector = this.forward(pos)
|
|
60
|
+
const posVector = this.forward([pos])[0]
|
|
59
61
|
const x = new Float32Array(xEM[0].length)
|
|
60
62
|
for (let a = 0; a < tokenVector.length; a++) {
|
|
61
63
|
x[a] = tokenVector[a] + posVector[a]
|
package/src/ReLU/index.d.ts
CHANGED
package/src/ReLU/index.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import { GPUHiddenLayer } from "../gpiInit.js";
|
|
2
|
+
|
|
1
3
|
export class ReLU{
|
|
2
4
|
input;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
gpu;
|
|
6
|
+
constructor(){
|
|
7
|
+
this.gpu = new GPUHiddenLayer()
|
|
6
8
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
for(let i = 0; i < outputGradient.length; i++){
|
|
10
|
-
inputGradient[i] = this.input[i] > 0 ? outputGradient[i] : 0
|
|
11
|
-
}
|
|
12
|
-
return inputGradient
|
|
9
|
+
forward(logits){
|
|
10
|
+
return this.gpu.forward(logits)
|
|
13
11
|
}
|
|
12
|
+
backward(outGradient){
|
|
13
|
+
return this.gpu.backward(outGradient)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
ClearInputCache(){}
|
|
14
17
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Softmax } from '../../index.js';
|
|
2
|
+
import { GPUAttention } from '../gpiInit.js';
|
|
2
3
|
import { Linear } from '../Linear/index.js'
|
|
3
4
|
|
|
4
5
|
export class SelfAttention {
|
|
@@ -13,6 +14,7 @@ export class SelfAttention {
|
|
|
13
14
|
score;
|
|
14
15
|
softmax;
|
|
15
16
|
weights;
|
|
17
|
+
gpu;
|
|
16
18
|
constructor(embeddingSize, configs) {
|
|
17
19
|
this.configs = configs
|
|
18
20
|
this.softmax = new Softmax()
|
|
@@ -22,99 +24,30 @@ export class SelfAttention {
|
|
|
22
24
|
this.value = new Linear(embeddingSize, embeddingSize, { save: { filename: [`${configs.dirname}/value.bin`, `${configs.dirname}/valueBias.bin`] } })
|
|
23
25
|
}
|
|
24
26
|
forward(vectors) {
|
|
27
|
+
if(!this.gpu) this.gpu = new GPUAttention(vectors[0].length, vectors.length);
|
|
25
28
|
this.q = this.query.forward(vectors)
|
|
26
29
|
this.v = this.value.forward(vectors)
|
|
27
30
|
this.k = this.key.forward(vectors)
|
|
28
|
-
const attentionSocres =
|
|
29
|
-
|
|
30
|
-
attentionSocres[i] = new Float32Array(this.k.length);
|
|
31
|
-
|
|
32
|
-
for (let j = 0; j < this.k.length; j++) {
|
|
33
|
-
if (j > i) {
|
|
34
|
-
attentionSocres[i][j] = -1e9; // mask future
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
let dot = 0;
|
|
39
|
-
|
|
40
|
-
for (let d = 0; d < this.q[i].length; d++) {
|
|
41
|
-
dot += this.q[i][d] * this.k[j][d];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
attentionSocres[i][j] = dot / this.score;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
this.softmax.forward(attentionSocres)
|
|
48
|
-
const weights = this.softmax.getSoftmaxes()
|
|
31
|
+
const attentionSocres = this.gpu.attentionScores(this.q, this.k, this.score);
|
|
32
|
+
const weights = this.softmax.forward(attentionSocres)
|
|
49
33
|
this.weights = weights
|
|
50
|
-
const output =
|
|
51
|
-
|
|
52
|
-
for (let i = 0; i < weights.length; i++) {
|
|
53
|
-
output[i] = new Float32Array(this.v[0].length);
|
|
54
|
-
|
|
55
|
-
for (let j = 0; j < this.v.length; j++) {
|
|
56
|
-
for (let d = 0; d < this.v[j].length; d++) {
|
|
57
|
-
output[i][d] += weights[i][j] * this.v[j][d];
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
34
|
+
const output = this.gpu.attentionOutput(weights, this.v)
|
|
62
35
|
return output;
|
|
63
36
|
}
|
|
64
|
-
softmaxBack(probs, dOut) {
|
|
65
|
-
const dIn = new Float32Array(probs.length);
|
|
66
|
-
|
|
67
|
-
for (let i = 0; i < probs.length; i++) {
|
|
68
|
-
let sum = 0;
|
|
69
37
|
|
|
70
|
-
for (let j = 0; j < probs.length; j++) {
|
|
71
|
-
const jacobian =
|
|
72
|
-
i === j
|
|
73
|
-
? probs[i] * (1 - probs[i])
|
|
74
|
-
: -probs[i] * probs[j];
|
|
75
|
-
|
|
76
|
-
sum += jacobian * dOut[j];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
dIn[i] = sum;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return dIn;
|
|
83
|
-
}
|
|
84
38
|
backward(dOutput, learningRate) {
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
for (let r = 0; r < this.v[j].length; r++) {
|
|
91
|
-
dWeights[a][j] += dOutput[a][r] * this.v[j][r]
|
|
92
|
-
dV[j][r] += dOutput[a][r] * this.weights[a][j]
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const dScores = []
|
|
97
|
-
for (let t = 0; t < dWeights.length; t++) {
|
|
98
|
-
dScores[t] = this.softmaxBack(this.weights[t], dWeights[t])
|
|
99
|
-
}
|
|
100
|
-
const dQ = this.q.map(q => new Float32Array(q.length));
|
|
101
|
-
const dK = this.k.map(k => new Float32Array(k.length));
|
|
102
|
-
for (let a = 0; a < this.q.length; a++) {
|
|
103
|
-
for (let j = 0; j < this.k.length; j++) {
|
|
104
|
-
if (j > a) continue;
|
|
105
|
-
for (let r = 0; r < this.q[a].length; r++) {
|
|
106
|
-
dQ[a][r] += dScores[a][j] * this.k[j][r] / this.score;
|
|
107
|
-
dK[j][r] += dScores[a][j] * this.q[a][r] / this.score;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
39
|
+
const dWeights = this.gpu.dWeightsKernel(dOutput, this.v)
|
|
40
|
+
const dV = this.gpu.dVKernel(dOutput, this.weights);
|
|
41
|
+
const dScores = this.gpu.softmaxBackKernel(this.weights, dWeights)
|
|
42
|
+
const dQ = this.gpu.dQKernel(dScores, this.k, this.score)
|
|
43
|
+
const dK = this.gpu.dKKernel(dScores, this.q, this.score)
|
|
111
44
|
const dInput = this.q.map(() => new Float32Array(this.q[0].length))
|
|
45
|
+
const dq = this.query.backward(dQ, learningRate)
|
|
46
|
+
const dk = this.key.backward(dK, learningRate)
|
|
47
|
+
const dv = this.value.backward(dV, learningRate)
|
|
112
48
|
for (let a = 0; a < this.q.length; a++) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const dv = this.value.backward(dV[a], learningRate, a)
|
|
116
|
-
for (let b = 0; b < dq.length; b++) {
|
|
117
|
-
dInput[a][b] = dq[b] + dk[b] + dv[b]
|
|
49
|
+
for (let b = 0; b < dq[a].length; b++) {
|
|
50
|
+
dInput[a][b] = dq[a][b] + dk[a][b] + dv[a][b]
|
|
118
51
|
}
|
|
119
52
|
}
|
|
120
53
|
return dInput
|
|
@@ -124,7 +57,7 @@ export class SelfAttention {
|
|
|
124
57
|
this.key.Save()
|
|
125
58
|
this.value.Save()
|
|
126
59
|
}
|
|
127
|
-
ClearInputCache(){
|
|
60
|
+
ClearInputCache() {
|
|
128
61
|
this.query.ClearInputCache()
|
|
129
62
|
this.key.ClearInputCache()
|
|
130
63
|
this.value.ClearInputCache()
|
package/src/Softmax/index.d.ts
CHANGED
package/src/Softmax/index.js
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GPUSoftmax } from "../gpiInit.js";
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
export class Softmax{
|
|
4
5
|
gpu;
|
|
5
|
-
constructor(contextSize){
|
|
6
|
-
this.gpu = new gpuSoftmax(contextSize)
|
|
7
|
-
}
|
|
8
6
|
forward(xLi){
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return this.gpu.
|
|
7
|
+
if(!this.gpu){
|
|
8
|
+
this.gpu = new GPUSoftmax(xLi, xLi.length)
|
|
9
|
+
}
|
|
10
|
+
return this.gpu.forward(xLi)
|
|
13
11
|
}
|
|
14
|
-
|
|
15
|
-
return this.gpu.
|
|
12
|
+
backward(xLi , target){
|
|
13
|
+
return this.gpu.backward(xLi, target)
|
|
16
14
|
}
|
|
17
15
|
crossEntropy(probs, target){
|
|
18
|
-
return this.gpu.
|
|
16
|
+
return this.gpu.crossEntropy(probs, target)
|
|
19
17
|
}
|
|
20
18
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { SelfAttention } from '../SelfAttention/index.js'
|
|
2
2
|
import { FFN } from '../FFN/index.js'
|
|
3
|
+
import fs from 'fs'
|
|
3
4
|
export class TransformerBlock {
|
|
4
5
|
ffn;
|
|
5
6
|
selfAttention;
|
|
6
7
|
constructor(embeddingSize, configs) {
|
|
7
|
-
|
|
8
|
+
if(!fs.existsSync(configs.dirname)) fs.mkdirSync(configs.dirname)
|
|
9
|
+
this.ffn = new FFN(embeddingSize, configs.activation, configs)
|
|
8
10
|
this.selfAttention = new SelfAttention(embeddingSize, configs)
|
|
9
11
|
}
|
|
10
12
|
forward(input) {
|