@@ -34,8 +34,8 @@ void Kernel(int i)
34
34
public static unsafe void ActivationBackward ( in Tensor x , in Tensor y , [ NotNull ] ActivationFunction f_ , in Tensor dx )
35
35
{
36
36
// Check
37
- if ( ! y . MatchShape ( x ) ) throw new ArgumentException ( nameof ( y ) , "The input tensors must have the same shape" ) ;
38
- if ( ! dx . MatchShape ( x ) ) throw new ArgumentException ( nameof ( y ) , "The output tensor must have the same shape as the input" ) ;
37
+ if ( ! y . MatchShape ( x ) ) throw new ArgumentException ( "The input tensors must have the same shape" , nameof ( y ) ) ;
38
+ if ( ! dx . MatchShape ( x ) ) throw new ArgumentException ( "The output tensor must have the same shape as the input" , nameof ( y ) ) ;
39
39
int
40
40
n = x . Entities ,
41
41
l = x . Length ;
@@ -55,5 +55,107 @@ void Kernel(int i)
55
55
}
56
56
57
57
#endregion
58
+
59
+ #region Fully connected
60
+
61
+ public static unsafe void FullyConnectedForward ( in Tensor x , in Tensor w , in Tensor b , in Tensor y )
62
+ {
63
+ // Initialize the parameters and the result matrix
64
+ if ( x . Length != w . Entities ) throw new ArgumentOutOfRangeException ( "Invalid tensors shapes" ) ;
65
+ if ( ! b . MatchShape ( 1 , w . Length ) ) throw new ArgumentException ( "Invalid biases shape" , nameof ( b ) ) ;
66
+ if ( ! y . MatchShape ( x . Entities , w . Length ) ) throw new ArgumentException ( "The output tensor doesn't have the right shape" , nameof ( y ) ) ;
67
+ int
68
+ h = x . Entities ,
69
+ l = x . Length ,
70
+ k = w . Length ;
71
+ float * pdy = y , px = x , pw = w , pb = b ;
72
+
73
+ // Execute the multiplication in parallel
74
+ void Kernel ( int i )
75
+ {
76
+ int offset = i * l ;
77
+ for ( int j = 0 ; j < k ; j ++ )
78
+ {
79
+ // Perform the multiplication
80
+ int start = j ;
81
+ float res = 0 ;
82
+ for ( int q = 0 ; q < l ; q ++ , start += k )
83
+ {
84
+ res += px [ offset + q ] * pw [ start ] ;
85
+ }
86
+ pdy [ i * k + j ] = res + pb [ j ] ; // Sum the input vector to each component
87
+ }
88
+ }
89
+ Parallel . For ( 0 , h , Kernel ) . AssertCompleted ( ) ;
90
+ }
91
+
92
+ public static unsafe void FullyConnectedBackwardData ( in Tensor x , in Tensor w , in Tensor dy , [ NotNull ] ActivationFunction f_ , in Tensor dx )
93
+ {
94
+ if ( w . Entities != x . Length ) throw new ArgumentException ( "The weights tensor doesn't have a valid shape" , nameof ( w ) ) ;
95
+ if ( ! x . MatchShape ( dy . Entities , w . Entities ) ) throw new ArgumentException ( "The input tensor doesn't have the right shape" , nameof ( x ) ) ;
96
+ if ( ! dx . MatchShape ( x ) ) throw new ArgumentException ( "The output tensor doesn't have the right shape" , nameof ( dx ) ) ;
97
+ Tensor . New ( w . Length , w . Entities , out Tensor wt ) ;
98
+ CpuBlas . Transpose ( w , wt ) ;
99
+
100
+ // Initialize the parameters and the result matrix
101
+ int
102
+ h = dy . Entities ,
103
+ l = dy . Length ,
104
+ k = wt . Length ;
105
+ float * pdx = dx , px = x , pdy = dy , pwt = wt ;
106
+
107
+ // Execute the multiplication in parallel
108
+ void Kernel ( int i )
109
+ {
110
+ int i1 = i * l ;
111
+ for ( int j = 0 ; j < k ; j ++ )
112
+ {
113
+ // Perform the multiplication
114
+ int i2 = j ;
115
+ float res = 0 ;
116
+ for ( int q = 0 ; q < l ; q ++ , i2 += k )
117
+ {
118
+ res += pdy [ i1 + q ] * pwt [ i2 ] ;
119
+ }
120
+
121
+ // res has now the matrix multiplication result for position [i, j]
122
+ int zIndex = i * k + j ;
123
+ pdx [ zIndex ] = f_ ( px [ zIndex ] ) * res ;
124
+ }
125
+ }
126
+ Parallel . For ( 0 , h , Kernel ) . AssertCompleted ( ) ;
127
+ wt . Free ( ) ;
128
+ }
129
+
130
+ public static void FullyConnectedBackwardFilter ( in Tensor x , in Tensor dy , in Tensor dw )
131
+ {
132
+ if ( x . Entities != dy . Entities ) throw new ArgumentException ( "The input tensor doesn't match the number of samples from the delta" , nameof ( x ) ) ;
133
+ Tensor . New ( x . Length , x . Entities , out Tensor xt ) ;
134
+ CpuBlas . Transpose ( x , xt ) ;
135
+ CpuBlas . Multiply ( xt , dy , dw ) ;
136
+ xt . Free ( ) ;
137
+ }
138
+
139
+ public static unsafe void FullyConnectedBackwardBias ( in Tensor dy , in Tensor db )
140
+ {
141
+ // Preliminary checks and declarations
142
+ if ( ! db . MatchShape ( 1 , dy . Length ) ) throw new ArgumentException ( "The output tensor doesn't have the right shape" , nameof ( db ) ) ;
143
+ int
144
+ n = dy . Entities ,
145
+ l = dy . Length ;
146
+ float * pdy = dy , pdb = db ;
147
+
148
+ // Compress the matrix
149
+ void Kernel ( int j )
150
+ {
151
+ float sum = 0 ;
152
+ for ( int i = 0 ; i < n ; i ++ )
153
+ sum += pdb [ i * l + j ] ;
154
+ pdy [ j ] = sum ;
155
+ }
156
+ Parallel . For ( 0 , l , Kernel ) . AssertCompleted ( ) ;
157
+ }
158
+
159
+ #endregion
58
160
}
59
161
}
0 commit comments