github.com/wzzhu/tensor@v0.9.24/example_dense_matop_test.go (about) 1 package tensor 2 3 import ( 4 "fmt" 5 ) 6 7 func ExampleDense_Slice() { 8 var T Tensor 9 T = New(WithBacking(Range(Float64, 0, 9)), WithShape(3, 3)) 10 fmt.Printf("T:\n%v\n", T) 11 12 // T[0:2, 0:2] 13 T, _ = T.Slice(makeRS(0, 2), makeRS(0, 2)) // makeRS is an unexported function that creates a Slice. 14 fmt.Printf("T[0:2, 0:2]:\n%v\n", T) 15 16 // T[:, 1] 17 T, _ = T.(Slicer).Slice(nil, ss(1)) // ss is unexported 18 fmt.Printf("T[:, 1]:\n%v\n", T) 19 20 // Output: 21 // T: 22 // ⎡0 1 2⎤ 23 // ⎢3 4 5⎥ 24 // ⎣6 7 8⎦ 25 // 26 // T[0:2, 0:2]: 27 // ⎡0 1⎤ 28 // ⎣3 4⎦ 29 // 30 // T[:, 1]: 31 // [1 4] 32 } 33 34 // Slicing works on one dimensional arrays too: 35 func ExampleDense_Slice_oneDimension() { 36 var T Tensor 37 T = New(WithBacking(Range(Float64, 0, 9))) 38 fmt.Printf("T:\n%v\n\n", T) 39 40 T, _ = T.Slice(makeRS(0, 5)) 41 fmt.Printf("T[0:5]:\n%v\n", T) 42 43 // Output: 44 // T: 45 // [0 1 2 3 ... 5 6 7 8] 46 // 47 // T[0:5]: 48 // [0 1 2 3 4] 49 50 } 51 52 // Any modifications to the sliced value modifies the original slice as well 53 func ExampleDense_Slice_viewMutation() { 54 var T, V Tensor 55 T = New(WithBacking(Range(Int, 0, 16)), WithShape(4, 4)) 56 fmt.Printf("T:\n%v\n", T) 57 V, _ = T.Slice(makeRS(1, 3), makeRS(1, 3)) 58 fmt.Printf("V:\n%v\n", V) 59 60 // Now we modify V's 0th value 61 V.(*Dense).Set(0, 1000) 62 fmt.Printf("V[0] = 1000:\n%v\n", V) 63 fmt.Printf("T is also mutated:\n%v", T) 64 65 // Output: 66 // T: 67 // ⎡ 0 1 2 3⎤ 68 // ⎢ 4 5 6 7⎥ 69 // ⎢ 8 9 10 11⎥ 70 // ⎣12 13 14 15⎦ 71 // 72 // V: 73 // ⎡ 5 6⎤ 74 // ⎣ 9 10⎦ 75 // 76 // V[0] = 1000: 77 // ⎡1000 6⎤ 78 // ⎣ 9 10⎦ 79 // 80 // T is also mutated: 81 // ⎡ 0 1 2 3⎤ 82 // ⎢ 4 1000 6 7⎥ 83 // ⎢ 8 9 10 11⎥ 84 // ⎣ 12 13 14 15⎦ 85 // 86 } 87 88 func ExampleView() { 89 // Slicing creates a "view" on the original tensor 90 T := New(WithBacking(Range(Int, 0, 16)), WithShape(4, 4)) 91 fmt.Printf("T:\n%v\n", T) 92 V, _ := T.Slice(makeRS(1, 3), makeRS(1, 3)) 93 fmt.Printf("V:\n%v\n", V) 94 95 // Now we modify V's 0th value 96 V.(*Dense).Set(0, 1000) 97 fmt.Printf("V[0] = 1000:\n%v\n", V) 98 fmt.Printf("T is also mutated:\n%v\n", T) 99 100 // Now we materialize the views 101 fmt.Printf("V is Materializable: %v\n", V.IsMaterializable()) 102 T2 := V.Materialize() 103 fmt.Printf("T2 == V:\n%v\n", T2) 104 105 // Once materialized, it is decoupled from the original tensor 106 T2.(*Dense).Set(0, 999) 107 fmt.Printf("T2 is mutated:\n%v\nBut T is not mutated:\n%v\nNeither is V:\n%v", T2, T, V) 108 // Output: 109 // T: 110 // ⎡ 0 1 2 3⎤ 111 // ⎢ 4 5 6 7⎥ 112 // ⎢ 8 9 10 11⎥ 113 // ⎣12 13 14 15⎦ 114 // 115 // V: 116 // ⎡ 5 6⎤ 117 // ⎣ 9 10⎦ 118 // 119 // V[0] = 1000: 120 // ⎡1000 6⎤ 121 // ⎣ 9 10⎦ 122 // 123 // T is also mutated: 124 // ⎡ 0 1 2 3⎤ 125 // ⎢ 4 1000 6 7⎥ 126 // ⎢ 8 9 10 11⎥ 127 // ⎣ 12 13 14 15⎦ 128 // 129 // V is Materializable: true 130 // T2 == V: 131 // ⎡1000 6⎤ 132 // ⎣ 9 10⎦ 133 // 134 // T2 is mutated: 135 // ⎡999 6⎤ 136 // ⎣ 9 10⎦ 137 // 138 // But T is not mutated: 139 // ⎡ 0 1 2 3⎤ 140 // ⎢ 4 1000 6 7⎥ 141 // ⎢ 8 9 10 11⎥ 142 // ⎣ 12 13 14 15⎦ 143 // 144 // Neither is V: 145 // ⎡1000 6⎤ 146 // ⎣ 9 10⎦ 147 148 } 149 150 func ExampleDense_Hstack() { 151 var T, T1, T2, T3 *Dense 152 var err error 153 T = New(WithBacking(Range(Float64, 0, 4)), WithShape(2, 2)) 154 T1 = New(WithBacking([]float64{1000, 2000}), WithShape(2, 1)) 155 156 // Simple example 157 if T2, err = T.Hstack(T1); err == nil { 158 fmt.Printf("T.Hstack(T1):\n%v\n", T2) 159 } 160 161 // This fails, because they are not the same shape 162 T1.Reshape(2) 163 if _, err = T.Hstack(T1); err != nil { 164 fmt.Printf("Error: %v\n\n", err) 165 } 166 167 // You can stack more than one, as long as all the tensors have the same shape 168 T1.Reshape(2, 1) 169 T3 = T1.Clone().(*Dense) 170 if T2, err = T.Hstack(T1, T3); err == nil { 171 fmt.Printf("T.Hstack(T1, T3):\n%v\n", T2) 172 } 173 174 // Compatible shapes can be stacked 175 T1 = New(Of(Float64), WithShape(2, 3)) 176 if T2, err = T.Hstack(T1); err == nil { 177 fmt.Printf("Hstacking (2,2) with (2,3):\n%v\n", T2) 178 } 179 180 // Special attention to vectors - vectors can only be stacked with vectors 181 T = New(WithBacking([]float64{1000, 2000})) 182 T1 = New(WithBacking([]float64{0, 1}), WithShape(1, 2)) 183 if _, err = T.Hstack(T1); err != nil { 184 fmt.Printf("Hstacking (2) with (1,2): %v\n", err) 185 } 186 187 // Now let's look at failure conditions, or unhandled situations 188 189 // Incompatible shapes cannot be stacked 190 T1.Reshape(3, 2) 191 if _, err = T.Hstack(T1); err != nil { 192 fmt.Printf("Hstacking (2,2) with (3,2): %v\n", err) 193 } 194 195 // Obviously you can't stack a scalar onto tensors (or the other way around) 196 T1 = New(FromScalar(1.0)) 197 if _, err = T.Hstack(T1); err != nil { 198 fmt.Printf("Hstacking a scalar onto a tensor: %v\n", err) 199 } 200 if _, err = T1.Hstack(T); err != nil { 201 fmt.Printf("Hstacking a tensor onto a scalar: %v\n", err) 202 } 203 204 // Output: 205 // T.Hstack(T1): 206 // ⎡ 0 1 1000⎤ 207 // ⎣ 2 3 2000⎦ 208 // 209 // Error: Failed to perform Concat: Unable to find new shape that results from concatenation: Dimension mismatch. Expected 2, got 1 210 // 211 // T.Hstack(T1, T3): 212 // ⎡ 0 1 1000 1000⎤ 213 // ⎣ 2 3 2000 2000⎦ 214 // 215 // Hstacking (2,2) with (2,3): 216 // ⎡0 1 0 0 0⎤ 217 // ⎣2 3 0 0 0⎦ 218 // 219 // Hstacking (2) with (1,2): Failed to perform Concat: Unable to find new shape that results from concatenation: Dimension mismatch. Expected 1, got 2 220 // Hstacking (2,2) with (3,2): Failed to perform Concat: Unable to find new shape that results from concatenation: Dimension mismatch. Expected 1, got 2 221 // Hstacking a scalar onto a tensor: Tensor has to be at least 1 dimensions 222 // Hstacking a tensor onto a scalar: Tensor has to be at least 1 dimensions 223 } 224 225 func ExampleDense_Vstack() { 226 var T, T1, T2, T3 *Dense 227 var err error 228 229 T = New(WithBacking(Range(Float64, 0, 4)), WithShape(2, 2)) 230 T1 = New(WithBacking([]float64{1000, 2000}), WithShape(1, 2)) 231 232 // Simple example 233 if T2, err = T.Vstack(T1); err == nil { 234 fmt.Printf("T.Vstack(T1):\n%v\n", T2) 235 } else { 236 fmt.Printf("%+v", err) 237 } 238 239 // You can stack more than one, as long as all the tensors have the same shape 240 T3 = T1.Clone().(*Dense) 241 if T2, err = T.Vstack(T1, T3); err == nil { 242 fmt.Printf("T.Vstack(T1, T3):\n%v\n", T2) 243 } else { 244 fmt.Printf("====\nerr %v\n%v\n===\n", err, T3.Shape()) 245 } 246 247 // Let's look at failure conditions 248 // All tensors must be at least 2D 249 T.Reshape(4) 250 if _, err = T.Vstack(T1); err != nil { 251 fmt.Printf("Vstacking (4) with (1, 2): %v\n", err) 252 } 253 if _, err = T1.Vstack(T); err != nil { 254 fmt.Printf("Vstacking (1, 2) with (4): %v\n", err) 255 } 256 257 // Output: 258 // T.Vstack(T1): 259 // ⎡ 0 1⎤ 260 // ⎢ 2 3⎥ 261 // ⎣1000 2000⎦ 262 // 263 // T.Vstack(T1, T3): 264 // ⎡ 0 1⎤ 265 // ⎢ 2 3⎥ 266 // ⎢1000 2000⎥ 267 // ⎣1000 2000⎦ 268 // 269 // Vstacking (4) with (1, 2): Tensor has to be at least 2 dimensions 270 // Vstacking (1, 2) with (4): Tensor has to be at least 2 dimensions 271 } 272 273 func ExampleRepeatReuse() { 274 var T, T1 *Dense 275 T = New(WithBacking([]float64{1, 2, 3, 4}), WithShape(1, 4)) 276 T1 = New(Of(Float64), WithShape(3, 4)) 277 278 var T2 Tensor 279 var err error 280 if T2, err = RepeatReuse(T, T1, 0, 3); err != nil { 281 fmt.Printf("Err %v", err) 282 } 283 fmt.Printf("RepeatReuse(T, T1):\n%v", T2) 284 fmt.Printf("T1 == T2: %t\n", T1 == T2) 285 286 // But if your reuse is wrongly shaped, an error occurs 287 T1 = New(Of(Float64), WithShape(1, 4)) // too small 288 if _, err = RepeatReuse(T, T1, 0, 3); err != nil { 289 fmt.Printf("Expected Error: %v\n", err) 290 } 291 292 // Output: 293 // RepeatReuse(T, T1): 294 // ⎡1 2 3 4⎤ 295 // ⎢1 2 3 4⎥ 296 // ⎣1 2 3 4⎦ 297 // T1 == T2: true 298 // Expected Error: Reuse shape is (1, 4). Expected shape is (3, 4) 299 } 300 301 func ExampleRepeat_uncommonUses() { 302 T := New(WithBacking([]int{1, 2, 3, 4, 5, 6}), WithShape(2, 3)) 303 fmt.Printf("T:\n%v", T) 304 305 fmt.Println("Axis 0 has 2 elements. So we will need to write the number of times each element is to be repeated") 306 fmt.Println("Here, Repeat(T, 0, 3, 2) results in this:") 307 T1, err := Repeat(T, 0, 3, 2) 308 if err != nil { 309 fmt.Printf("Err %v", err) 310 } 311 fmt.Printf("%v", T1) 312 fmt.Println("Observe the 0th element ([1 2 3]) has been repeated 3 times, and the 1st element ([4 5 6]) has been repeated twice") 313 fmt.Println("") 314 315 fmt.Println("We can also repeat on Axis 1. Now along Axis 1 there are 3 elements: ([1 4], [2 5], [3 6])") 316 fmt.Println("So we have to specify how many times to repeat each element.") 317 fmt.Println("Repeat(T, 1, 2, 3, 2) yields the following result:") 318 T1, err = Repeat(T, 1, 2, 3, 2) 319 if err != nil { 320 fmt.Printf("Err %v", err) 321 } 322 fmt.Printf("%v", T1) 323 fmt.Println("Once again, observe that the 1st element ([2 5]) has been repeated 3 times, while the rest have been repeated twice") 324 /* 325 // TODO break this out to another example 326 T1, err = Repeat(T, AllAxes, 2, 3, 2, 2, 2, 2) 327 if err != nil { 328 fmt.Printf("Err %v", err) 329 } 330 fmt.Printf("%#v", T1) 331 */ 332 333 // Output: 334 // T: 335 // ⎡1 2 3⎤ 336 // ⎣4 5 6⎦ 337 // Axis 0 has 2 elements. So we will need to write the number of times each element is to be repeated 338 // Here, Repeat(T, 0, 3, 2) results in this: 339 // ⎡1 2 3⎤ 340 // ⎢1 2 3⎥ 341 // ⎢1 2 3⎥ 342 // ⎢4 5 6⎥ 343 // ⎣4 5 6⎦ 344 // Observe the 0th element ([1 2 3]) has been repeated 3 times, and the 1st element ([4 5 6]) has been repeated twice 345 // 346 // We can also repeat on Axis 1. Now along Axis 1 there are 3 elements: ([1 4], [2 5], [3 6]) 347 // So we have to specify how many times to repeat each element. 348 // Repeat(T, 1, 2, 3, 2) yields the following result: 349 // ⎡1 1 2 2 2 3 3⎤ 350 // ⎣4 4 5 5 5 6 6⎦ 351 // Once again, observe that the 1st element ([2 5]) has been repeated 3 times, while the rest have been repeated twice 352 353 } 354 355 func ExampleT() { 356 // Usual example of 2D matrix being transposed: 357 M := New(WithBacking([]int{1, 2, 3, 4, 5, 6}), WithShape(2, 3)) 358 M2, err := T(M) 359 if err != nil { 360 fmt.Printf("Err: %v\n", err) 361 } 362 fmt.Printf("M:\n%v\nM2:\n%v\n", M, M2) 363 364 // T accepts optional parameters describing the permutation of axes. 365 // In a 2D case, there are only two options: (0, 1) or (1, 0). 366 // The latter is default if no parameters are passed in. 367 // The former is a no-op as rearranging a matrix so that the 0th axis becomes the 0th axis 368 // and the first axis becomes the first axis is not going to do anything. 369 // 370 // However, note that M3 is a different result. 371 M3, err := T(M, 0, 1) 372 if err != nil { 373 fmt.Printf("Err: %v\n", err) 374 } 375 fmt.Printf("M3:\n%v\nM == M3: %t", M3, M == M3) 376 377 // Output: 378 // M: 379 // ⎡1 2 3⎤ 380 // ⎣4 5 6⎦ 381 // 382 // M2: 383 // ⎡1 4⎤ 384 // ⎢2 5⎥ 385 // ⎣3 6⎦ 386 // 387 // M3: 388 // ⎡1 2 3⎤ 389 // ⎣4 5 6⎦ 390 // 391 // M == M3: false 392 393 } 394 395 func ExampleT_scalarlike() { 396 // Be aware when dealing with scalarlike tensors 397 // scalar/scalarlikes have no effect when calling T() 398 // but the result is put into a new tensor 399 S := New(WithBacking([]float32{3.14}), WithShape()) 400 S2, err := T(S) 401 if err != nil { 402 fmt.Printf("Err %v", err) 403 } 404 fmt.Printf("S: %v S2 %v S == S2: %t\n", S, S2, S == S2) 405 406 // however do note that scalars and scalarlikes are not the same thing. 407 // for example, consider this: 408 _, err = T(S, 1, 0) 409 fmt.Printf("error when the axes are more than the shape's dims: %v\n", err) 410 411 // but if you have a tensor that is a scalar-like: 412 S.Reshape(1, 1) 413 S2, err = T(S, 1, 0) 414 if err != nil { 415 fmt.Printf("Err: %v\n", err) 416 } 417 fmt.Printf("S:\n%v\nS2:\n%v\nS == S2: %t\n", S, S2, S == S2) 418 419 // Output: 420 // S: 3.14 S2 3.14 S == S2: false 421 // error when the axes are more than the shape's dims: Dimension mismatch. Expected 0, got 2 422 // S: 423 // [[3.14]] 424 // S2: 425 // [[3.14]] 426 // S == S2: false 427 428 }