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  }