@mineproness/tensorloop 1.5.8 → 2.0.0
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/index.js +0 -2
- package/package.json +1 -1
- package/src/Embedding/index.js +7 -2
- package/src/GPU.js +162 -43
- package/src/Linear/index.d.ts +2 -2
- package/src/Linear/index.js +13 -8
- package/src/SelfAttention/index.js +10 -4
- package/src/Softmax/index.d.ts +4 -2
- package/src/Softmax/index.js +16 -9
- package/src/crossEntropy/index.js +0 -3
package/index.js
CHANGED
|
@@ -2,7 +2,6 @@ import { Tokenizer as tokenizer } from "./src/Tokenizer/index.js";
|
|
|
2
2
|
import { Embedding as embeddding2 } from "./src/Embedding/index.js";
|
|
3
3
|
import { Linear as li2 } from "./src/Linear/index.js";
|
|
4
4
|
import { Softmax as softmax2 } from "./src/Softmax/index.js";
|
|
5
|
-
import { crossEntropy } from "./src/crossEntropy/index.js";
|
|
6
5
|
import {ReLU} from './src/ReLU/index.js'
|
|
7
6
|
import {PositionEmbedding as PE} from './src/PositionEmbedding/index.js'
|
|
8
7
|
import {SelfAttention as ST} from './src/SelfAttention/index.js'
|
|
@@ -13,7 +12,6 @@ export const Tokenizer = tokenizer
|
|
|
13
12
|
export const Embedding = embeddding2
|
|
14
13
|
export const Linear = li2
|
|
15
14
|
export const Softmax = softmax2
|
|
16
|
-
export const CrossEntropy = crossEntropy
|
|
17
15
|
export const ReLu = ReLU
|
|
18
16
|
export const PositionEmbedding = PE
|
|
19
17
|
export const SelfAttention = ST
|
package/package.json
CHANGED
package/src/Embedding/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs, { existsSync } from 'fs'
|
|
2
2
|
import { SaveVectors, LoadVectors } from '../GetConfigs.js'
|
|
3
|
-
import { GPUEmbedding } from '../GPU.js'
|
|
3
|
+
// import { GPUEmbedding } from '../GPU.js'
|
|
4
4
|
// import { config } from 'process'
|
|
5
5
|
|
|
6
6
|
function GenerateVectors(embeddingSize, vocabSize) {
|
|
@@ -43,11 +43,16 @@ export class Embedding {
|
|
|
43
43
|
return this.vectors[token]
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
backwards(token, inputGradient, learingRate) {
|
|
47
47
|
for (let a = 0; a < this.vectors[token].length; a++) {
|
|
48
48
|
this.vectors[token][a] -= learingRate * inputGradient[a]
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
backward(tokens, inputGradient, learingRate){
|
|
52
|
+
for(let a = 0; a < inputGradient.length; a++){
|
|
53
|
+
this.backwards(tokens[a], inputGradient[a], learingRate)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
51
56
|
Save() {
|
|
52
57
|
SaveVectors(this.vectors, this.configs.save.filename)
|
|
53
58
|
}
|
package/src/GPU.js
CHANGED
|
@@ -18,24 +18,32 @@ export function splitMatrix(matrix, chunksSizes = maxSize) {
|
|
|
18
18
|
return { split: true, data: chunks }
|
|
19
19
|
|
|
20
20
|
}
|
|
21
|
+
let outputSizes = [];
|
|
22
|
+
let out = 0
|
|
21
23
|
export class GPULinear {
|
|
22
24
|
cacheLF = [];
|
|
23
25
|
cacheLBIas = [];
|
|
24
26
|
cacheLBWeights = [];
|
|
25
27
|
cacheLBInputGradent = [];
|
|
26
28
|
// texures
|
|
29
|
+
contextSize;
|
|
30
|
+
weightLength = 0;
|
|
27
31
|
Bias = [];
|
|
28
32
|
Weights = []
|
|
29
|
-
InitKernel(weights, bias, size) {
|
|
33
|
+
InitKernel(weights, bias, size, contextSize) {
|
|
30
34
|
const splitedWeights = splitMatrix(weights)
|
|
31
35
|
const splitedBias = splitMatrix(bias)
|
|
36
|
+
this.weightLength = weights.length
|
|
32
37
|
this.Weights = splitedWeights.data
|
|
38
|
+
out = weights.length
|
|
33
39
|
this.Bias = splitedBias.data
|
|
34
40
|
for (let a = 0; a < splitedWeights.data.length; a++) {
|
|
41
|
+
outputSizes.push(splitedWeights.data[a].length)
|
|
42
|
+
|
|
35
43
|
this.cacheLF[a] = gpu.createKernel(function (input, bias, weights) {
|
|
36
44
|
let sum = bias[this.thread.x]
|
|
37
45
|
for (let a = 0; a < this.constants.inputLength; a++) {
|
|
38
|
-
sum += input[a] * weights[this.thread.x][a]
|
|
46
|
+
sum += input[this.thread.y][a] * weights[this.thread.x][a]
|
|
39
47
|
}
|
|
40
48
|
return sum
|
|
41
49
|
}).setConstants({
|
|
@@ -44,22 +52,25 @@ export class GPULinear {
|
|
|
44
52
|
input: 'Array',
|
|
45
53
|
bias: 'Array',
|
|
46
54
|
weights: 'Array'
|
|
47
|
-
}).setOutput([splitedWeights.data[a].length])
|
|
55
|
+
}).setOutput([splitedWeights.data[a].length, contextSize])
|
|
48
56
|
this.cacheLBIas[a] = gpu.createKernel(function (
|
|
49
57
|
bias,
|
|
50
58
|
outputGradient,
|
|
51
59
|
learningRate
|
|
52
60
|
) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
let grad = 0;
|
|
62
|
+
for (let a = 0; a < this.constants.contextSize; a++) {
|
|
63
|
+
const g = outputGradient[a][this.thread.x]
|
|
64
|
+
|
|
65
|
+
grad += g
|
|
66
|
+
}
|
|
57
67
|
|
|
58
68
|
return bias[this.thread.x] - learningRate * grad
|
|
59
69
|
}, {
|
|
60
70
|
pipeline: true,
|
|
61
71
|
immutable: true,
|
|
62
|
-
output: [splitedWeights.data[a].length]
|
|
72
|
+
output: [splitedWeights.data[a].length, contextSize],
|
|
73
|
+
constants: { contextSize }
|
|
63
74
|
})
|
|
64
75
|
this.cacheLBInputGradent[a] = gpu.createKernel(function (
|
|
65
76
|
weights,
|
|
@@ -68,93 +79,201 @@ export class GPULinear {
|
|
|
68
79
|
let sum = 0
|
|
69
80
|
|
|
70
81
|
for (let a = 0; a < this.constants.outputSize; a++) {
|
|
71
|
-
const grad =
|
|
72
|
-
-1,
|
|
73
|
-
Math.min(1, outputGradient[a])
|
|
74
|
-
)
|
|
75
|
-
|
|
82
|
+
const grad = outputGradient[this.thread.y][a]
|
|
76
83
|
sum += grad * weights[a][this.thread.x]
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
return sum
|
|
80
87
|
}, {
|
|
81
88
|
constants: { outputSize: splitedWeights.data[a].length },
|
|
82
|
-
output: [size]
|
|
89
|
+
output: [size, contextSize]
|
|
83
90
|
})
|
|
84
|
-
|
|
91
|
+
|
|
85
92
|
this.cacheLBWeights[a] = gpu.createKernel(function (
|
|
86
93
|
weights,
|
|
87
94
|
outputGradient,
|
|
88
95
|
input,
|
|
89
96
|
learningRate
|
|
90
97
|
) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
let grad = 0;
|
|
99
|
+
for (let a = 0; a < this.constants.contextSize; a++) {
|
|
100
|
+
grad += outputGradient[a][this.thread.y] * input[a][this.thread.x]
|
|
101
|
+
}
|
|
95
102
|
|
|
96
103
|
return weights[this.thread.y][this.thread.x]
|
|
97
|
-
- learningRate *
|
|
104
|
+
- learningRate * grad
|
|
98
105
|
}, {
|
|
99
106
|
pipeline: true,
|
|
100
107
|
immutable: true,
|
|
101
|
-
output: [size, splitedWeights.data[a].length]
|
|
108
|
+
output: [size, splitedWeights.data[a].length],
|
|
109
|
+
constants: { contextSize }
|
|
102
110
|
})
|
|
103
111
|
}
|
|
104
112
|
|
|
105
|
-
|
|
113
|
+
this.contextSize = contextSize
|
|
106
114
|
|
|
107
115
|
}
|
|
108
116
|
CalculateLinearForward(input) {
|
|
109
|
-
const result =
|
|
117
|
+
const result = Array.from({ length: this.contextSize },
|
|
118
|
+
() => new Float32Array(this.weightLength)
|
|
119
|
+
)
|
|
110
120
|
let offset = 0;
|
|
111
121
|
for (let a = 0; a < this.Weights.length; a++) {
|
|
112
122
|
const output = this.cacheLF[a](input, this.Bias[a], this.Weights[a])
|
|
113
|
-
|
|
123
|
+
for (let y = 0; y < this.contextSize; y++) {
|
|
124
|
+
result[y].set(output[y], offset);
|
|
125
|
+
}
|
|
126
|
+
offset += this.Weights[a].length
|
|
114
127
|
|
|
115
128
|
}
|
|
116
129
|
return result
|
|
117
130
|
}
|
|
118
131
|
CalculateBackward(out, learningRate, input) {
|
|
119
|
-
let inputGradient = new Float32Array(input.length)
|
|
132
|
+
let inputGradient = Array.from({ length: this.contextSize } , ()=> new Float32Array(input[0].length))
|
|
120
133
|
for (let a = 0; a < this.Weights.length; a++) {
|
|
121
134
|
const outGradient = this.cacheLBInputGradent[a](this.Weights[a], out)
|
|
122
|
-
for (let
|
|
123
|
-
|
|
135
|
+
for (let row = 0; row < this.contextSize; row++) {
|
|
136
|
+
for (let i = 0; i < input[0].length; i++) {
|
|
137
|
+
inputGradient[row][i] += outGradient[row][i];
|
|
138
|
+
}
|
|
124
139
|
}
|
|
125
140
|
const oldW = this.Weights[a]
|
|
126
141
|
const oldB = this.Bias[a]
|
|
127
142
|
this.Weights[a] = this.cacheLBWeights[a](this.Weights[a], out, input, learningRate)
|
|
128
143
|
this.Bias[a] = this.cacheLBIas[a](this.Bias[a], out, learningRate)
|
|
129
|
-
if(oldW && typeof oldW.delete === "function"){
|
|
144
|
+
if (oldW && typeof oldW.delete === "function") {
|
|
130
145
|
oldW.delete()
|
|
131
146
|
}
|
|
132
|
-
|
|
147
|
+
if (oldB && typeof oldB.delete === "function") {
|
|
133
148
|
oldB.delete()
|
|
134
149
|
}
|
|
135
150
|
|
|
136
151
|
}
|
|
137
152
|
return inputGradient
|
|
138
153
|
}
|
|
139
|
-
GetWeightsAndBias(){
|
|
154
|
+
GetWeightsAndBias() {
|
|
140
155
|
const weight = []
|
|
141
156
|
const bias = []
|
|
142
|
-
this.Weights.map((e)=> weight.push(...e.toArray()))
|
|
143
|
-
this.Bias.map((e)=> bias.push(...e.toArray()))
|
|
144
|
-
return { weights: weight, bias: new Float32Array(bias)}
|
|
157
|
+
this.Weights.map((e) => weight.push(...e.toArray()))
|
|
158
|
+
this.Bias.map((e) => bias.push(...e.toArray()))
|
|
159
|
+
return { weights: weight, bias: new Float32Array(bias) }
|
|
145
160
|
}
|
|
146
161
|
}
|
|
147
162
|
|
|
148
|
-
export class
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
163
|
+
export class gpuSoftmax {
|
|
164
|
+
cacheSF = [];
|
|
165
|
+
cacheSB = [];
|
|
166
|
+
contextSize;
|
|
167
|
+
Probs = [];
|
|
168
|
+
LossCalculate;
|
|
169
|
+
constructor(contextSize) {
|
|
170
|
+
this.contextSize = contextSize;
|
|
171
|
+
for (let a = 0; a < outputSizes.length; a++) {
|
|
172
|
+
this.cacheSF[a] = gpu.createKernel(function (logits) {
|
|
173
|
+
let maxLogits = logits[this.thread.y][0];
|
|
174
|
+
let sum = 0;
|
|
175
|
+
for (let a = 0; a < this.constants.outputSize; a++) {
|
|
176
|
+
if (logits[this.thread.y][a] > maxLogits) {
|
|
177
|
+
maxLogits = logits[this.thread.y][a]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
for (let a = 0; a < this.constants.outputSize; a++) {
|
|
181
|
+
sum += Math.exp(logits[this.thread.y][a] - maxLogits)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return Math.exp(logits[this.thread.y][this.thread.x] - maxLogits) / sum
|
|
185
|
+
|
|
186
|
+
}, {
|
|
187
|
+
pipeline: true,
|
|
188
|
+
immutable: true,
|
|
189
|
+
output: [outputSizes[a], contextSize],
|
|
190
|
+
constants: { outputSize: outputSizes[a] }
|
|
191
|
+
})
|
|
192
|
+
this.cacheSB[a] = gpu.createKernel(function (probs, target) {
|
|
193
|
+
const p = probs[this.thread.y][this.thread.x]
|
|
194
|
+
if (this.thread.x == target[this.thread.y]) {
|
|
195
|
+
return p - 1.0
|
|
196
|
+
}
|
|
197
|
+
return p
|
|
198
|
+
}, {
|
|
199
|
+
output: [outputSizes[a], contextSize]
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
this.LossCalculate = gpu.createKernel(function (probs, target) {
|
|
203
|
+
const tar = target[this.thread.x]
|
|
204
|
+
return -Math.log((probs[this.thread.x][tar] + 1) + 1e-10)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
}, {
|
|
208
|
+
output: [contextSize]
|
|
209
|
+
})
|
|
154
210
|
}
|
|
155
|
-
|
|
156
|
-
|
|
211
|
+
forwardSoftmax(logits) {
|
|
212
|
+
const splitedLogits = splitMatrix(logits)
|
|
213
|
+
for (let a = 0; a < splitedLogits.data.length; a++) {
|
|
214
|
+
const oldSoftmax = this.Probs[a]
|
|
215
|
+
this.Probs[a] = this.cacheSF[a](splitedLogits.data[a])
|
|
216
|
+
if (oldSoftmax && typeof oldSoftmax.delete == "function") {
|
|
217
|
+
oldSoftmax.delete()
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return "Completed"
|
|
157
221
|
}
|
|
158
|
-
|
|
159
|
-
|
|
222
|
+
getSoftmax() {
|
|
223
|
+
const result = Array.from({ length: this.contextSize }, () => new Float32Array(out))
|
|
224
|
+
let offset = 0;
|
|
225
|
+
for (let a = 0; a < this.Probs.length; a++) {
|
|
226
|
+
const outputofSoftmax = this.Probs[a].toArray()
|
|
227
|
+
for (let a = 0; a < this.contextSize; a++) {
|
|
228
|
+
result[a].set(outputofSoftmax[a], offset)
|
|
229
|
+
}
|
|
230
|
+
offset += outputofSoftmax[0].length
|
|
231
|
+
}
|
|
232
|
+
return result
|
|
233
|
+
}
|
|
234
|
+
softmaxBackward(target) {
|
|
235
|
+
const result = Array.from(
|
|
236
|
+
{ length: this.contextSize },
|
|
237
|
+
() => new Float32Array(out)
|
|
238
|
+
);
|
|
239
|
+
let offset = 0;
|
|
240
|
+
for (let chunk = 0; chunk < this.Probs.length; chunk++) {
|
|
241
|
+
const chunkSize = outputSizes[chunk];
|
|
242
|
+
const localTarget = new Int32Array(this.contextSize);
|
|
243
|
+
for (let row = 0; row < this.contextSize; row++) {
|
|
244
|
+
const globalTarget = target[row];
|
|
245
|
+
if (
|
|
246
|
+
globalTarget >= offset &&
|
|
247
|
+
globalTarget < offset + chunkSize
|
|
248
|
+
) {
|
|
249
|
+
localTarget[row] = globalTarget - offset;
|
|
250
|
+
} else {
|
|
251
|
+
localTarget[row] = -1;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const gradient = this.cacheSB[chunk](
|
|
255
|
+
this.Probs[chunk],
|
|
256
|
+
localTarget
|
|
257
|
+
);
|
|
258
|
+
const data = gradient;
|
|
259
|
+
for (let row = 0; row < this.contextSize; row++) {
|
|
260
|
+
result[row].set(data[row], offset);
|
|
261
|
+
}
|
|
262
|
+
offset += chunkSize;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
calculateLOSS(dLogits, target) {
|
|
268
|
+
const losses = this.LossCalculate(dLogits, target)
|
|
269
|
+
let loss = 0;
|
|
270
|
+
|
|
271
|
+
for (let i = 0; i < losses.length; i++) {
|
|
272
|
+
loss += losses[i];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
loss /= losses.length;
|
|
276
|
+
return loss
|
|
277
|
+
}
|
|
278
|
+
|
|
160
279
|
}
|
package/src/Linear/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export class Linear{
|
|
2
2
|
Weights : Float32Array[]
|
|
3
3
|
Bias: Float32Array
|
|
4
|
-
constructor(embeddingSize : number, vocabSize : number, configs: {
|
|
4
|
+
constructor(embeddingSize : number, vocabSize : number, contextSiz: number, configs: {
|
|
5
5
|
save: {
|
|
6
6
|
filename: string[]
|
|
7
7
|
}
|
|
8
8
|
})
|
|
9
|
-
forward(input :
|
|
9
|
+
forward(input : Float32Array[]) : Float32Array[]
|
|
10
10
|
backward(outGradient : number[] , learingRate: number, idx: number) : Float32Array[]
|
|
11
11
|
Save() : void
|
|
12
12
|
ClearInputCache() : void
|
package/src/Linear/index.js
CHANGED
|
@@ -20,7 +20,7 @@ export class Linear {
|
|
|
20
20
|
configs;
|
|
21
21
|
input = [];
|
|
22
22
|
gpu;
|
|
23
|
-
constructor(embeddingSize, vocabSize, configs) {
|
|
23
|
+
constructor(embeddingSize, vocabSize, contextSize, 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])) {
|
|
@@ -41,7 +41,7 @@ export class Linear {
|
|
|
41
41
|
this.Bias = Bias;
|
|
42
42
|
}
|
|
43
43
|
this.gpu = new GPULinear()
|
|
44
|
-
this.gpu.InitKernel(this.Weights, this.Bias, embeddingSize)
|
|
44
|
+
this.gpu.InitKernel(this.Weights, this.Bias, embeddingSize, contextSize)
|
|
45
45
|
}
|
|
46
46
|
Save() {
|
|
47
47
|
const {bias, weights} = this.gpu.GetWeightsAndBias()
|
|
@@ -49,16 +49,21 @@ export class Linear {
|
|
|
49
49
|
SaveBias(bias, this.configs.save.filename[1])
|
|
50
50
|
}
|
|
51
51
|
forward(input) {
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
const result = []
|
|
53
|
+
for(let a = 0;a < input.length; a++){
|
|
54
|
+
this.input[a] = input;
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
return this.gpu.CalculateLinearForward(input)
|
|
54
58
|
}
|
|
55
|
-
backward(outputGradient, learningRate
|
|
56
|
-
const input = this.input
|
|
57
|
-
const weights = this.Weights
|
|
59
|
+
backward(outputGradient, learningRate) {
|
|
60
|
+
const input = this.input;
|
|
58
61
|
const inputGradient = this.gpu.CalculateBackward(outputGradient, learningRate, input)
|
|
59
62
|
return inputGradient
|
|
60
63
|
}
|
|
61
64
|
ClearInputCache(){
|
|
62
65
|
this.input = []
|
|
63
66
|
}
|
|
64
|
-
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
@@ -22,9 +22,9 @@ export class SelfAttention {
|
|
|
22
22
|
this.value = new Linear(embeddingSize, embeddingSize, { save: { filename: [`${configs.dirname}/value.bin`, `${configs.dirname}/valueBias.bin`] } })
|
|
23
23
|
}
|
|
24
24
|
forward(vectors) {
|
|
25
|
-
this.q =
|
|
26
|
-
this.v =
|
|
27
|
-
this.k =
|
|
25
|
+
this.q = this.query.forward(vectors)
|
|
26
|
+
this.v = this.value.forward(vectors)
|
|
27
|
+
this.k = this.key.forward(vectors)
|
|
28
28
|
const attentionSocres = []
|
|
29
29
|
for (let i = 0; i < this.q.length; i++) {
|
|
30
30
|
attentionSocres[i] = new Float32Array(this.k.length);
|
|
@@ -44,7 +44,8 @@ export class SelfAttention {
|
|
|
44
44
|
attentionSocres[i][j] = dot / this.score;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
this.softmax.forward(attentionSocres)
|
|
48
|
+
const weights = this.softmax.getSoftmaxes()
|
|
48
49
|
this.weights = weights
|
|
49
50
|
const output = [];
|
|
50
51
|
|
|
@@ -123,4 +124,9 @@ export class SelfAttention {
|
|
|
123
124
|
this.key.Save()
|
|
124
125
|
this.value.Save()
|
|
125
126
|
}
|
|
127
|
+
ClearInputCache(){
|
|
128
|
+
this.query.ClearInputCache()
|
|
129
|
+
this.key.ClearInputCache()
|
|
130
|
+
this.value.ClearInputCache()
|
|
131
|
+
}
|
|
126
132
|
}
|
package/src/Softmax/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export class Softmax{
|
|
2
|
-
forward(xLi : number[]) : number
|
|
3
|
-
backward(
|
|
2
|
+
forward(xLi : number[]) : number
|
|
3
|
+
backward(target : number[]) : Float32Array[]
|
|
4
|
+
getSoftmaxes() : Float32Array[]
|
|
5
|
+
crossEntropy(dLogits: Float32Array[], target: number[])
|
|
4
6
|
}
|
package/src/Softmax/index.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
import { gpuSoftmax } from "../GPU.js";
|
|
2
|
+
|
|
1
3
|
export class Softmax{
|
|
4
|
+
gpu;
|
|
5
|
+
constructor(contextSize){
|
|
6
|
+
this.gpu = new gpuSoftmax(contextSize)
|
|
7
|
+
}
|
|
2
8
|
forward(xLi){
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
return this.gpu.forwardSoftmax(xLi)
|
|
10
|
+
}
|
|
11
|
+
backward(target){
|
|
12
|
+
return this.gpu.softmaxBackward(target)
|
|
13
|
+
}
|
|
14
|
+
getSoftmaxes(){
|
|
15
|
+
return this.gpu.getSoftmax()
|
|
16
|
+
}
|
|
17
|
+
crossEntropy(probs, target){
|
|
18
|
+
return this.gpu.calculateLOSS(probs, target)
|
|
12
19
|
}
|
|
13
20
|
}
|