163 lines
3.8 KiB
Go
163 lines
3.8 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"git.kingecg.top/kingecg/gotensor"
|
||
"math"
|
||
)
|
||
|
||
func main() {
|
||
fmt.Println("=== 线性回归示例 ===")
|
||
|
||
// 创建简单的线性回归数据: y = 2*x + 3
|
||
// X = [[1, x1], [1, x2], ...] (添加偏置项)
|
||
// w = [b, w1] (偏置和权重)
|
||
|
||
// 准备训练数据
|
||
x_data := []float64{1.0, 2.0, 3.0, 4.0, 5.0}
|
||
X, err := gotensor.NewTensor(x_data, []int{5, 1})
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
// 创建设计矩阵,添加偏置列
|
||
X_with_bias, err := addBiasColumn(X)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
// 真实的y值: y = 2*x + 3
|
||
y_data := []float64{5.0, 7.0, 9.0, 11.0, 13.0} // 2*x + 3
|
||
Y, err := gotensor.NewTensor(y_data, []int{5, 1})
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
// 初始化权重 [b, w] = [0, 0]
|
||
w_data := []float64{0.0, 0.0}
|
||
W, err := gotensor.NewTensor(w_data, []int{2, 1})
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
fmt.Printf("训练数据 X (带偏置):\n%s\n", X_with_bias.String())
|
||
fmt.Printf("目标值 Y:\n%s\n", Y.String())
|
||
fmt.Printf("初始权重 W:\n%s\n", W.String())
|
||
|
||
// 训练参数
|
||
learning_rate := 0.01
|
||
epochs := 100
|
||
|
||
for epoch := 0; epoch < epochs; epoch++ {
|
||
// 前向传播: Y_pred = X * W
|
||
Y_pred, err := X_with_bias.MatMul(W)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
// 计算损失: MSE = (1/n) * sum((Y_pred - Y)^2)
|
||
diff, err := Y_pred.Subtract(Y)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
// 计算平方差
|
||
squared_diff, err := diff.Multiply(diff)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
// 计算平均值(简单地用一个常数缩放)
|
||
// 在完整实现中,我们需要一个求平均的函数,这里简化处理
|
||
loss_val := sumTensor(squared_diff) / float64(squared_diff.Size())
|
||
|
||
if epoch % 20 == 0 {
|
||
fmt.Printf("Epoch %d, Loss: %.6f\n", epoch, loss_val)
|
||
}
|
||
|
||
// 计算梯度
|
||
// MSE梯度: dL/dW = (2/n) * X^T * (Y_pred - Y)
|
||
X_transpose, err := X_with_bias.Data.Transpose()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
X_T := &gotensor.Tensor{Data: X_transpose}
|
||
|
||
grad_W_intermediate, err := X_T.MatMul(diff)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
grad_W := grad_W_intermediate.Scale(2.0 / float64(X_with_bias.Size()))
|
||
|
||
// 更新权重: W = W - lr * grad_W
|
||
grad_update := grad_W.Scale(learning_rate)
|
||
W, err = W.Subtract(grad_update)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
}
|
||
|
||
fmt.Printf("\n训练后的权重 W:\n%s\n", W.String())
|
||
|
||
// 预测
|
||
Y_pred, err := X_with_bias.MatMul(W)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
fmt.Printf("预测值:\n%s\n", Y_pred.String())
|
||
fmt.Printf("真实值:\n%s\n", Y.String())
|
||
|
||
// 计算最终误差
|
||
diff, err := Y_pred.Subtract(Y)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
squared_diff, err := diff.Multiply(diff)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
final_loss := sumTensor(squared_diff) / float64(squared_diff.Size())
|
||
fmt.Printf("最终损失: %.6f\n", final_loss)
|
||
}
|
||
|
||
// 辅助函数:为输入矩阵添加偏置列
|
||
func addBiasColumn(X *gotensor.Tensor) (*gotensor.Tensor, error) {
|
||
shape := X.Shape()
|
||
rows := shape[0]
|
||
|
||
// 这里需要实现列拼接,暂时使用简单的拼接方法
|
||
// 实际上我们需要一个拼接函数,这里用一个近似的方法
|
||
// 由于当前API没有提供拼接功能,我们手动构造
|
||
result_data := make([]float64, rows*2)
|
||
for i := 0; i < rows; i++ {
|
||
result_data[i*2] = 1.0 // 偏置项
|
||
X_val, _ := X.Data.Get(i, 0)
|
||
result_data[i*2+1] = X_val
|
||
}
|
||
|
||
return gotensor.NewTensor(result_data, []int{rows, 2})
|
||
}
|
||
|
||
// 辅助函数:计算张量所有元素的和
|
||
func sumTensor(t *gotensor.Tensor) float64 {
|
||
sum := 0.0
|
||
shape := t.Shape()
|
||
if len(shape) == 2 {
|
||
rows, cols := shape[0], shape[1]
|
||
for i := 0; i < rows; i++ {
|
||
for j := 0; j < cols; j++ {
|
||
val, _ := t.Data.Get(i, j)
|
||
sum += val
|
||
}
|
||
}
|
||
} else {
|
||
size := t.Size()
|
||
for i := 0; i < size; i++ {
|
||
val, _ := t.Data.Get(i)
|
||
sum += val
|
||
}
|
||
}
|
||
return math.Abs(sum) // 使用绝对值避免负数和
|
||
} |