introduce RelU methods

This commit is contained in:
TreetopFlyer 2021-07-30 23:06:38 -04:00
parent b1c95d4819
commit 3861d41c83
3 changed files with 36 additions and 24 deletions

View File

@ -11,10 +11,10 @@ Deno.test("Iterate.Loop", ()=>
assertEquals(cloud[0][0], 0); assertEquals(cloud[0][0], 0);
assertEquals(cloud[3][2], 5, "correct output"); assertEquals(cloud[3][2], 5, "correct output");
}); });
Deno.test("Iterate.Edit", ()=> Deno.test("Iterate.Copy", ()=>
{ {
const c = [[1, 2], [3, 4]] const c = [[1, 2], [3, 4]]
const t = M.Iterate.Edit(c, (i)=>i); const t = M.Iterate.Copy(c, (i)=>i);
assertEquals(t.length, c.length, "correct count"); assertEquals(t.length, c.length, "correct count");
assertEquals(t[0][0], c[0][0], "correct dimensions"); assertEquals(t[0][0], c[0][0], "correct dimensions");
assertEquals(t[1][1], c[1][1], "correct placement"); assertEquals(t[1][1], c[1][1], "correct placement");
@ -146,20 +146,39 @@ Deno.test("Batch.Subtract", ()=>
assertEquals(t[0].length, 2, "correct dimensions"); assertEquals(t[0].length, 2, "correct dimensions");
assertEquals(t[1][0], 2.5, "correct placement"); assertEquals(t[1][0], 2.5, "correct placement");
}); });
Deno.test("Batch.Sigmoid", ()=> Deno.test("Batch.Sig", ()=>
{ {
const m = [[-1000, 1000]]; const m = [[-1000, 1000]];
const t = M.Batch.Sigmoid(m); const t = M.Batch.Sig(m);
assertEquals(t.length, 1, "correct count"); assertEquals(t.length, 1, "correct count");
assertEquals(t[0].length, 2, "correct dimensions"); assertEquals(t[0].length, 2, "correct dimensions");
assert(t[0][0]>=0 && t[0][0]<0.5); assert(t[0][0]>=0 && t[0][0]<0.5);
assert(t[0][1]<=1 && t[0][1]>0.5, "correct placement"); assert(t[0][1]<=1 && t[0][1]>0.5, "correct placement");
}); });
Deno.test("Batch.Derivative", ()=> Deno.test("Batch.SigDeriv", ()=>
{ {
const m = [[-1000, 0, 1000]]; const m = [[-1000, 0, 1000]];
const t = M.Batch.Derivative(M.Batch.Sigmoid(m)); const t = M.Batch.SigDeriv(M.Batch.Sig(m));
assertEquals(t.length, 1, "correct count"); assertEquals(t.length, 1, "correct count");
assertEquals(t[0].length, 3, "correct dimensions"); assertEquals(t[0].length, 3, "correct dimensions");
assert(t[0][0]<t[0][1] && t[0][1]>t[0][2]); assert(t[0][0]<t[0][1] && t[0][1]>t[0][2]);
}); });
Deno.test("Batch.Rec", ()=>
{
const m = [[-1, 1, 10]];
const t = M.Batch.Rec(m);
assert(t[0][0] == 0);
assert(t[0][1] == 1);
assert(t[0][2] == 10);
});
Deno.test("Batch.RecDeriv", ()=>
{
const m = [[-1, 1, 10]];
const t = M.Batch.RecDeriv(m);
assert(t[0][0] == 0);
assert(t[0][1] == 1);
assert(t[0][2] == 1);
});

25
m.ts
View File

@ -16,22 +16,20 @@ const Methods = {
for(i=0; i<inCount; i++) for(i=0; i<inCount; i++)
{ {
outputVector = []; outputVector = [];
for(j=0; j<inDimensions; j++) for(j=0; j<inDimensions; j++){ outputVector.push(inFunction(j, i, outputVector)); }
{
outputVector.push(inFunction(j, i, outputVector));
}
outputCloud.push(outputVector); outputCloud.push(outputVector);
} }
return outputCloud; return outputCloud;
}, },
Edit: (inCloud:Cloud.M, inFunction:Cloud.HandleEdit):Cloud.M=> inCloud.map((row:Cloud.V):Cloud.V=>row.map(inFunction)) Copy: (inCloud:Cloud.M, inFunction:Cloud.HandleEdit):Cloud.M=> inCloud.map((row:Cloud.V):Cloud.V=> row.map(inFunction)),
Edit: (inCloud:Cloud.M, inFunction:Cloud.HandleEdit):void => inCloud.forEach((row:Cloud.V):void=>row.forEach(inFunction))
}, },
Create: Create:
{ {
Box: (inV1:Cloud.V, inV2:Cloud.V, inCount:number):Cloud.M=> Methods.Iterate.Loop(inV1.length, inCount, i=> inV1[i]+(inV2[i]-inV1[i])*Math.random()), Box: (inV1:Cloud.V, inV2:Cloud.V, inCount:number):Cloud.M=> Methods.Iterate.Loop(inV1.length, inCount, i=> inV1[i]+(inV2[i]-inV1[i])*Math.random()),
Transpose: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Loop(inCloud.length, inCloud[0].length, (i, row)=> inCloud[i][row]), Transpose: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Loop(inCloud.length, inCloud[0].length, (i, row)=> inCloud[i][row]),
Outer: (inV1:Cloud.V, inV2:Cloud.V):Cloud.M=> Methods.Iterate.Loop(inV1.length, inV2.length, (i, row)=> inV1[i]*inV2[row]), Outer: (inV1:Cloud.V, inV2:Cloud.V):Cloud.M=> Methods.Iterate.Loop(inV1.length, inV2.length, (i, row)=> inV1[i]*inV2[row]),
Clone: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Edit(inCloud, i=> i), Clone: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Copy(inCloud, i=> i),
Padded: (inCloud:Cloud.M):Cloud.M=> inCloud.map((row:Cloud.V)=> [...row, 1]) Padded: (inCloud:Cloud.M):Cloud.M=> inCloud.map((row:Cloud.V)=> [...row, 1])
}, },
Mutate: Mutate:
@ -39,13 +37,6 @@ const Methods = {
Pad: (inCloud:Cloud.M):Cloud.M=> {inCloud.forEach((row:Cloud.V)=> row.push(1)); return inCloud; }, Pad: (inCloud:Cloud.M):Cloud.M=> {inCloud.forEach((row:Cloud.V)=> row.push(1)); return inCloud; },
Unpad: (inCloud:Cloud.M):Cloud.M=> {inCloud.forEach((row:Cloud.V)=> row.pop()); return inCloud; } Unpad: (inCloud:Cloud.M):Cloud.M=> {inCloud.forEach((row:Cloud.V)=> row.pop()); return inCloud; }
}, },
Test:
{
Dot:(v1:Cloud.V, v2:Cloud.V):number=>
{
return v1.reduce((sum, current, index)=> sum + current*v2[index]);
}
},
Single: Single:
{ {
Subtract: (inV1:Cloud.V, inV2:Cloud.V):Cloud.V=> inV1.map((component, i)=> component-inV2[i]), Subtract: (inV1:Cloud.V, inV2:Cloud.V):Cloud.V=> inV1.map((component, i)=> component-inV2[i]),
@ -57,9 +48,11 @@ const Methods = {
Subtract: (inCloud1:Cloud.M, inCloud2:Cloud.M):Cloud.M=> inCloud1.map((row:Cloud.V, rowIndex:number)=> Methods.Single.Subtract(row, inCloud2[rowIndex])), Subtract: (inCloud1:Cloud.M, inCloud2:Cloud.M):Cloud.M=> inCloud1.map((row:Cloud.V, rowIndex:number)=> Methods.Single.Subtract(row, inCloud2[rowIndex])),
Multiply: (inCloud1:Cloud.M, inCloud2:Cloud.M):Cloud.M=> inCloud1.map((row:Cloud.V, rowIndex:number)=> Methods.Single.Multiply(row, inCloud2[rowIndex])), Multiply: (inCloud1:Cloud.M, inCloud2:Cloud.M):Cloud.M=> inCloud1.map((row:Cloud.V, rowIndex:number)=> Methods.Single.Multiply(row, inCloud2[rowIndex])),
Affine: (inCloud1:Cloud.M, inCloud2:Cloud.M):Cloud.M=> inCloud1.map((row:Cloud.V)=> Methods.Single.Affine(row, inCloud2)), Affine: (inCloud1:Cloud.M, inCloud2:Cloud.M):Cloud.M=> inCloud1.map((row:Cloud.V)=> Methods.Single.Affine(row, inCloud2)),
Sigmoid: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Edit(inCloud, i=>1/(1+Math.pow(Math.E, -i))), Sig: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Copy(inCloud, i=>1/(1+Math.pow(Math.E, -i))),
Derivative: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Edit(inCloud, i=>i*(1-i)), SigDeriv: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Copy(inCloud, i=>i*(1-i)),
Scale: (inCloud:Cloud.M, inScalar:number):Cloud.M=> Methods.Iterate.Edit(inCloud, i=>i*inScalar) Rec: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Copy(inCloud, i=> i<=0 ? 0 : i),
RecDeriv: (inCloud:Cloud.M):Cloud.M=> Methods.Iterate.Copy(inCloud, i=> i<=0 ? 0 : 1),
Scale: (inCloud:Cloud.M, inScalar:number):Cloud.M=> Methods.Iterate.Copy(inCloud, i=>i*inScalar)
} }
}; };

4
nn.ts
View File

@ -5,7 +5,7 @@ const Forward = (inData:Cloud.M, inLayers:N):N =>
{ {
let i:number; let i:number;
let stages:N = [inData]; let stages:N = [inData];
let process = (index:number):Cloud.M => M.Batch.Sigmoid(M.Batch.Affine(stages[index], inLayers[index])); let process = (index:number):Cloud.M => M.Batch.Sig(M.Batch.Affine(stages[index], inLayers[index]));
for(i=0; i<inLayers.length-1; i++){ stages[i+1] = M.Mutate.Pad(process(i)); } for(i=0; i<inLayers.length-1; i++){ stages[i+1] = M.Mutate.Pad(process(i)); }
stages[i+1] = process(i); stages[i+1] = process(i);
@ -18,7 +18,7 @@ const Backward = (inStages:N, inLayers:N, inGoals:Cloud.M, inRate:number):N =>
for(i=inLayers.length-1; i>=0; i--) for(i=inLayers.length-1; i>=0; i--)
{ {
let errorScaled:Cloud.M = M.Batch.Multiply(errorBack, M.Batch.Derivative(inStages[i+1])); let errorScaled:Cloud.M = M.Batch.Multiply(errorBack, M.Batch.SigDeriv(inStages[i+1]));
errorBack = M.Batch.Affine(errorScaled, M.Create.Transpose(inLayers[i])); errorBack = M.Batch.Affine(errorScaled, M.Create.Transpose(inLayers[i]));
errorScaled.forEach((inScaledError:Cloud.V, inIndex:number)=> errorScaled.forEach((inScaledError:Cloud.V, inIndex:number)=>
{ {