Skip to content

Commit 6c7d951

Browse files
committed
tensor:op
1 parent a904f81 commit 6c7d951

File tree

7 files changed

+211
-171
lines changed

7 files changed

+211
-171
lines changed

dl/layer/layer.go

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ import (
77
"git.array2d.com/ai/deepgo/dl"
88
)
99

10-
type f1_1 func(id int, input *dl.Tensor) *dl.Tensor
11-
type f2_1 func(id int, input1, input2 *dl.Tensor) *dl.Tensor
12-
type f1_2 func(id int, input *dl.Tensor) [2]*dl.Tensor
13-
type fN_1 func(id int, inputs []*dl.Tensor) *dl.Tensor
14-
type fN_N func(id int, inputs []*dl.Tensor) []*dl.Tensor
10+
type f1_1[T dl.Number] func(id int, input *dl.Tensor[T]) *dl.Tensor[T]
11+
type f2_1[T dl.Number] func(id int, input1, input2 *dl.Tensor[T]) *dl.Tensor[T]
12+
type f1_2[T dl.Number] func(id int, input *dl.Tensor[T]) [2]*dl.Tensor[T]
13+
type fN_1[T dl.Number] func(id int, inputs []*dl.Tensor[T]) *dl.Tensor[T]
14+
type fN_N[T dl.Number] func(id int, inputs []*dl.Tensor[T]) []*dl.Tensor[T]
1515

16-
type RWTensor struct {
17-
*dl.Tensor
16+
type RWTensor[T dl.Number] struct {
17+
*dl.Tensor[T]
1818
sync.RWMutex
1919
}
2020

21-
type ComputeGraphNode struct {
21+
type ComputeGraphNode[T dl.Number] struct {
2222
in, out int
2323
forward map[[2]int]any
2424
backward map[[2]int]any
@@ -27,16 +27,16 @@ type ComputeGraphNode struct {
2727
//linear的input0~n
2828
//activation的output0~n
2929
//weight.grad,bias.grad
30-
parameters map[string]*RWTensor
30+
parameters map[string]*RWTensor[T]
3131
attr map[string]any
3232
}
3333

3434
// NewNode 创建一个新的节点
35-
func NewNode(in, out int) *ComputeGraphNode {
36-
node := &ComputeGraphNode{
35+
func NewNode[T dl.Number](in, out int) *ComputeGraphNode[T] {
36+
node := &ComputeGraphNode[T]{
3737
in: in,
3838
out: out,
39-
parameters: make(map[string]*RWTensor, runtime.NumCPU()*2+4),
39+
parameters: make(map[string]*RWTensor[T], runtime.NumCPU()*2+4),
4040
attr: map[string]any{},
4141
forward: make(map[[2]int]any),
4242
backward: make(map[[2]int]any),
@@ -45,39 +45,39 @@ func NewNode(in, out int) *ComputeGraphNode {
4545
}
4646

4747
// SetAttr 注册一个参数
48-
func (n *ComputeGraphNode) SetAttr(name string, attr any) {
48+
func (n *ComputeGraphNode[T]) SetAttr(name string, attr any) {
4949
n.attr[name] = attr
5050
} // SetAttr 注册一个参数
51-
func (n *ComputeGraphNode) Attr(name string) (attr any) {
51+
func (n *ComputeGraphNode[T]) Attr(name string) (attr any) {
5252
return n.attr[name]
5353
}
5454

5555
// RegisterParameter 注册一个参数
56-
func (n *ComputeGraphNode) RegisterParameter(name string, param *dl.Tensor) {
56+
func (n *ComputeGraphNode[T]) RegisterParameter(name string, param *dl.Tensor[T]) {
5757
if _, ok := n.parameters[name]; !ok {
58-
n.parameters[name] = &RWTensor{}
58+
n.parameters[name] = &RWTensor[T]{}
5959
}
6060
n.parameters[name].Tensor = param
6161
}
6262

6363
// Parameters 返回所有注册的参数
64-
func (n *ComputeGraphNode) Parameter(name string) *RWTensor {
64+
func (n *ComputeGraphNode[T]) Parameter(name string) *RWTensor[T] {
6565
return n.parameters[name]
6666
}
6767

68-
func (n *ComputeGraphNode) Forward(id int, inputs ...*dl.Tensor) []*dl.Tensor {
68+
func (n *ComputeGraphNode[T]) Forward(id int, inputs ...*dl.Tensor[T]) []*dl.Tensor[T] {
6969
if f, ok := n.forward[[2]int{n.in, n.out}]; ok {
7070
switch f := f.(type) {
71-
case f1_1:
72-
return []*dl.Tensor{f(id, inputs[0])}
73-
case f2_1:
74-
return []*dl.Tensor{f(id, inputs[0], inputs[1])}
75-
case f1_2:
71+
case f1_1[T]:
72+
return []*dl.Tensor[T]{f(id, inputs[0])}
73+
case f2_1[T]:
74+
return []*dl.Tensor[T]{f(id, inputs[0], inputs[1])}
75+
case f1_2[T]:
7676
r := f(id, inputs[0])
77-
return []*dl.Tensor{r[0], r[1]}
78-
case fN_1:
79-
return []*dl.Tensor{f(id, inputs)}
80-
case fN_N:
77+
return []*dl.Tensor[T]{r[0], r[1]}
78+
case fN_1[T]:
79+
return []*dl.Tensor[T]{f(id, inputs)}
80+
case fN_N[T]:
8181
return f(id, inputs)
8282
}
8383
} else {
@@ -87,19 +87,19 @@ func (n *ComputeGraphNode) Forward(id int, inputs ...*dl.Tensor) []*dl.Tensor {
8787
}
8888

8989
// Backward 执行反向传播
90-
func (n *ComputeGraphNode) Backward(id int, gradients ...*dl.Tensor) []*dl.Tensor {
90+
func (n *ComputeGraphNode[T]) Backward(id int, gradients ...*dl.Tensor[T]) []*dl.Tensor[T] {
9191
if f, ok := n.backward[[2]int{n.in, n.out}]; ok {
9292
switch f := f.(type) {
93-
case f1_1:
94-
return []*dl.Tensor{f(id, gradients[0])}
95-
case f2_1:
96-
return []*dl.Tensor{f(id, gradients[0], gradients[1])}
97-
case f1_2:
93+
case f1_1[T]:
94+
return []*dl.Tensor[T]{f(id, gradients[0])}
95+
case f2_1[T]:
96+
return []*dl.Tensor[T]{f(id, gradients[0], gradients[1])}
97+
case f1_2[T]:
9898
r := f(id, gradients[0])
99-
return []*dl.Tensor{r[0], r[1]}
100-
case fN_1:
101-
return []*dl.Tensor{f(id, gradients)}
102-
case fN_N:
99+
return []*dl.Tensor[T]{r[0], r[1]}
100+
case fN_1[T]:
101+
return []*dl.Tensor[T]{f(id, gradients)}
102+
case fN_N[T]:
103103
return f(id, gradients)
104104
}
105105
}

dl/layer/linear.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import (
88
)
99

1010
// NewLinear 创建一个新的线性层,支持批处理
11-
func Linear(in_features, out_features int, biasInit bool) (l *ComputeGraphNode) {
12-
l = NewNode(1, 1)
11+
func Linear[T dl.Number](in_features, out_features int, biasInit bool) (l *ComputeGraphNode[T]) {
12+
l = NewNode[T](1, 1)
1313

1414
l.SetAttr("in_features", in_features)
1515
l.SetAttr("out_features", out_features)
1616
// 初始化权重和偏置,参考pytorch设计
17-
weight_ := dl.NewTensor([]int{out_features, in_features})
17+
weight_ := dl.NewTensor[T]([]int{out_features, in_features})
1818

1919
// 初始化权重
2020
//何凯明大神,永远的神!用了这个,loss下降飞快100倍
@@ -23,15 +23,15 @@ func Linear(in_features, out_features int, biasInit bool) (l *ComputeGraphNode)
2323

2424
if biasInit {
2525
// 初始化偏置
26-
biasT := dl.NewTensor([]int{out_features})
27-
fanIn, _ := dl.CalculateFanInAndFanOut(weight_)
26+
biasT := dl.NewTensor[T]([]int{out_features})
27+
fanIn, _ := weight_.CalculateFanInAndFanOut()
2828
bound := 1 / math.Sqrt(float64(fanIn))
2929
biasT.Uniform(-bound, bound)
3030
l.RegisterParameter("bias", biasT)
3131
} else {
32-
l.RegisterParameter("bias", dl.NewTensor([]int{out_features}))
32+
l.RegisterParameter("bias", dl.NewTensor[T]([]int{out_features}))
3333
}
34-
var f f1_1 = func(id int, input *dl.Tensor) (output *dl.Tensor) {
34+
var f f1_1[T] = func(id int, input *dl.Tensor[T]) (output *dl.Tensor[T]) {
3535
//由于backward需要input的梯度,所以这里需要保存input
3636
l.RegisterParameter("input"+strconv.Itoa(id), input)
3737
l.Parameter("weight").RLock()
@@ -43,9 +43,9 @@ func Linear(in_features, out_features int, biasInit bool) (l *ComputeGraphNode)
4343
return
4444
}
4545
l.forward[[2]int{1, 1}] = f
46-
l.RegisterParameter("weight.grad", dl.NewTensor([]int{out_features, in_features}))
47-
l.RegisterParameter("bias.grad", dl.NewTensor([]int{out_features}))
48-
var b f1_1 = func(id int, outputGrad *dl.Tensor) (inputGrad *dl.Tensor) {
46+
l.RegisterParameter("weight.grad", dl.NewTensor[T]([]int{out_features, in_features}))
47+
l.RegisterParameter("bias.grad", dl.NewTensor[T]([]int{out_features}))
48+
var b f1_1[T] = func(id int, outputGrad *dl.Tensor[T]) (inputGrad *dl.Tensor[T]) {
4949

5050
// 在计算weight.Grad时,需要的是该层的input
5151
// 获取当前层的输入,形状为 [batchSize, in_features]

dl/tensor.go

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package dl
33
import (
44
"fmt"
55
"math"
6-
"sort"
76
)
87

98
type Tensor[T Number] struct {
@@ -104,47 +103,6 @@ func (t *Tensor[T]) Range(dimCount int, f func(indices []int)) {
104103
f(indices) // 调用传入的函数
105104
}
106105
}
107-
func (t *Tensor[T]) SumDimMap(dims []int) (sumMap []int) {
108-
// Step 1: 确定输出形状
109-
sumDims := make([]int, len(dims))
110-
copy(sumDims, dims)
111-
sort.Ints(sumDims)
112-
// 去重
113-
sumDims = Unique(sumDims)
114-
115-
// 验证维度
116-
for _, d := range sumDims {
117-
if d < 0 || d >= len(t.Shape) {
118-
panic("Dimension out of range in sum")
119-
}
120-
}
121-
122-
// 创建一个映射数组,标记哪些维度需要求和
123-
sumMap = make([]int, len(t.Shape))
124-
for _, dim := range sumDims {
125-
sumMap[dim] = 1
126-
}
127-
return sumMap
128-
}
129-
func (t *Tensor[T]) SumShape(dims []int) []int {
130-
// 创建一个映射数组,标记哪些维度需要求和
131-
sumMap := t.SumDimMap(dims)
132-
133-
// 计算输出形状
134-
outputShape := make([]int, 0)
135-
136-
for i := 0; i < len(t.Shape); i++ {
137-
if sumMap[i] == 0 {
138-
outputShape = append(outputShape, t.Shape[i])
139-
}
140-
}
141-
142-
// 如果所有维度都被求和,返回标量张量
143-
if len(outputShape) == 0 {
144-
outputShape = append(outputShape, 1)
145-
}
146-
return outputShape
147-
}
148106

149107
// Print 打印Tensor的值
150108
func (t *Tensor[T]) Print(format_ ...string) {
@@ -222,84 +180,3 @@ func (t *Tensor[T]) Clone() *Tensor[T] {
222180
copy(clone.Data, t.Data)
223181
return clone
224182
}
225-
226-
func (t *Tensor[T]) Transpose(dimOrder []int) *Tensor[T] {
227-
if len(dimOrder) != len(t.Shape) {
228-
panic("dimOrder length must be equal to the number of dimensions in the tensor")
229-
}
230-
newShape := make([]int, len(t.Shape))
231-
for i, dim := range dimOrder {
232-
newShape[i] = t.Shape[dim]
233-
}
234-
result := NewTensor[T](newShape)
235-
if t.Len() != result.Len() {
236-
panic("transpose error: newShape:" + fmt.Sprint(newShape) + " oldShape:" + fmt.Sprint(t.Shape))
237-
}
238-
t.Range(len(dimOrder), func(indices []int) {
239-
newIndices := make([]int, len(indices))
240-
for i, dim := range dimOrder {
241-
newIndices[i] = indices[dim]
242-
}
243-
result.Set(newIndices, t.Get(indices...))
244-
})
245-
return result
246-
}
247-
func (t *Tensor[T]) Sum(dims []int) *Tensor[T] {
248-
// 创建一个映射数组,标记哪些维度需要求和
249-
sumMap := t.SumDimMap(dims)
250-
// 计算输出形状
251-
outputShape := t.SumShape(dims)
252-
253-
result := NewTensor[T](outputShape)
254-
255-
// Step 2: 使用 range 遍历输入张量
256-
t.Range(len(t.Shape), func(indices []int) {
257-
// 计算输出索引
258-
outputIndices := make([]int, len(result.Shape))
259-
for i, j := 0, 0; i < len(t.Shape); i++ {
260-
if sumMap[i] == 0 {
261-
outputIndices[j] = indices[i]
262-
j++
263-
}
264-
}
265-
266-
// 累加求和
267-
inputIdx := t.LinearAt(indices)
268-
outputIdx := result.LinearAt(outputIndices)
269-
result.Data[outputIdx] += t.Data[inputIdx]
270-
})
271-
return result
272-
}
273-
func (a *Tensor[T]) MatMulShape(b *Tensor[T]) (c []int) {
274-
if len(a.Shape) < 2 || len(b.Shape) < 2 {
275-
panic("TensorCPU dimensions do not match for multiplication")
276-
}
277-
if a.Shape[len(a.Shape)-1] != b.Shape[len(b.Shape)-2] {
278-
panic("TensorCPU dimensions do not match for multiplication")
279-
}
280-
resultShape := make([]int, len(a.Shape))
281-
copy(resultShape, a.Shape)
282-
resultShape[len(resultShape)-1] = b.Shape[len(b.Shape)-1]
283-
return resultShape
284-
}
285-
286-
// MatMul 实现高维矩阵 Tensor 的矩阵乘法
287-
// 矩阵的最后两维满足:A矩阵的列数B矩阵的行数相等
288-
func (a *Tensor[T]) MatMul(b *Tensor[T]) (c *Tensor[T]) {
289-
c = NewTensor[T](a.MatMulShape(b))
290-
c.Range(len(c.Shape)-2, func(indices []int) {
291-
aIdx := a.LinearAt(indices)
292-
bIdx := b.LinearAt(indices)
293-
cIdx := c.LinearAt(indices)
294-
295-
m, k, n := c.Shape[len(c.Shape)-2], a.Shape[len(a.Shape)-1], c.Shape[len(c.Shape)-1]
296-
for i := 0; i < m; i++ {
297-
for j := 0; j < n; j++ {
298-
for x := 0; x < k; x++ {
299-
c.Data[cIdx+i*n+j] += a.Data[aIdx+i*k+x] * b.Data[bIdx+x*n+j]
300-
}
301-
}
302-
}
303-
})
304-
return c
305-
}

dl/tensor_initializer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (t *Tensor[T]) Uniform(low, high float64) {
5959
// Linear 从 low 到 high 线性初始化张量
6060
func (t *Tensor[T]) Linear(low, high float64) {
6161
n := len(t.Data)
62-
step := (high - low) / float64(n)
62+
step := (high - low) / float64(n-1)
6363
for i := 0; i < n; i++ {
6464
t.Data[i] = T(low + float64(i)*step)
6565
}

0 commit comments

Comments
 (0)