import random
import torch
# ①根据带有噪声的线性模型构造一个人造数据集。 使用线性模型参数w=[2,−3.4] b=4.2和噪声项ϵ生成数据集及其标签
def synthetic_data(w, b, num_examples):
"""生成 y = Xw + b + 噪声。"""
# 生成均值为0,标准差为1,行为num_examples = 1000,列为len(w)=2的矩阵,也就是从一个标准正态分布N~(0,1),提取一个1000*2的矩阵。
X = torch.normal(0, 1, (num_examples, len(w)))
# 此时X为1000*2的矩阵,也就是二维张量,w为向量,也就是一维张量,符合normal运算的第四种情况,此时将w转置为列向量,也就是2*1的矩阵,做矩阵乘法结果为1000*1的列向量。
y = torch.matmul(X, w)+b
# 生成均值为0,标准差为0.01的噪声加上y,返回新的y
y += torch.normal(0, 0.01, y.shape)
# 返回X 将y转置成1列后返回
return X, y.reshape((-1, 1))
# 定义w
true_w = torch.tensor([2, -3.4])
# 定义b
true_b = 4.2
# 生成数据集和标签
features, labels = synthetic_data(true_w, true_b, 1000)
# 打印第一个特征和标签,观察数据集和特征格式
print('features:', features[0], '\nlabel:', labels[0])
# ②定义一个data_iter 函数, 该函数接收批量大小、特征矩阵和标签向量作为输入,生成大小为batch_size的小批量
def data_iter(batch_size, features, labels):
# features的len应该是1000
num_examples = len(features)
# rang(1000)的一个数据再list一下组成一个列表
indices = list(range(num_examples))
# 把序列进行一下乱序
random.shuffle(indices)
# 返回一个数据集和标签
for i in range(0, num_examples, batch_size):
batch_indices = torch.tensor(indices[i:min(i + batch_size, num_examples)])
yield features[batch_indices], labels[batch_indices]
# 定义尺寸
batch_size = 10
# 打印
for X, y in data_iter(batch_size, features, labels):
print(X, '\n', y)
break
# ③定义 初始化模型参数
w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
# ④定义模型
def linreg(X, w, b):
"""线性回归模型。"""
return torch.matmul(X, w) + b
# ⑤定义损失函数
def squared_loss(y_hat, y):
"""均方损失。"""
return (y_hat - y.reshape(y_hat.shape))**2 / 2
# ⑥定义优化算法
def sgd(params, lr, batch_size):
"""小批量随机梯度下降。"""
with torch.no_grad():
for param in params:
param -= lr * param.grad / batch_size
param.grad.zero_()
# ⑦训练过程
# 定义学习率(理解为梯度下降中的步长不知道对不对)
lr = 0.03
# 定义学习几轮
num_epochs = 5
# 定义网络
net = linreg
# 定义损失函数
loss = squared_loss
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, features, labels):
l = loss(net(X, w, b), y)
l.sum().backward()
sgd([w, b], lr, batch_size)
with torch.no_grad():
train_l = loss(net(features, w, b), labels)
print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
学习第三轮时候基本已经稳定
epoch 1, loss 0.035958
w的估计误差: tensor([ 0.0963, -0.1706])
b的估计误差: tensor([0.1828])
epoch 2, loss 0.000128
w的估计误差: tensor([ 0.0048, -0.0085])
b的估计误差: tensor([0.0081])
epoch 3, loss 0.000050
w的估计误差: tensor([ 0.0003, -0.0001])
b的估计误差: tensor([0.0006])
epoch 4, loss 0.000050
w的估计误差: tensor([4.5466e-04, 1.8120e-05])
b的估计误差: tensor([0.0004])
epoch 5, loss 0.000050
w的估计误差: tensor([3.6359e-05, 3.4094e-05])
b的估计误差: tensor([0.0004])
Process finished with exit code 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
2024年我的技术成长之路
大家好,我是小寒。又到年底了,一年过得真快啊!趁着这次活动的机会,和大家聊聊我这一年在技术上的收获和踩过的坑。
说实话,今年工作特别忙,写博客的时间比去年少了不少。不过还是坚持记录一些开发中遇到的问题和解决方案,毕竟这也是我最初写博客的初衷 - 给自己留个笔记,方便以后查阅。
没想到这些随手记录的文章,居然帮助到了不少遇到同样问题的小伙伴。经常看到有博友在评论区说"太感谢了,困扰了好久的问题终于解决了",每次看到这样的评论都特别有成就感!
一、Spring Cloud踩坑实录
说实话,年初接手一个大型电商的微服务项目时还挺懵的。连连支付的对接就让我头疼了好久,特别是处理异步通知和订单状态同步时翻了不少文档。最后总算搞定了,也写了几篇博客记录解决方案,没想到还挺受欢迎的。
最让我印象深刻的是解决了一个困扰团队很久的问题:连连支付异步通知总是出现重复通知的情况。当时私下和几个博友讨论了很多实现细节,比如如何处理网络超时、如何避免重复入账等问题,大家互相学习,收获很多。排查下来发现是幂等性处理的问题,小寒准备把这个经历也整理出一篇文章《支付系统异步通知幂等性解决方案》,希望后面能对大家有所帮助。
二、Vue3项目实战经验
今年主要在用Vue3重构我们的管理后台。说真的,从Vue2迁移到Vue3的过程并不轻松。特别是组合式API的使用,一开始真的不适应,老是想用选项式API的思维去写代码。
不过用着用着就发现Vue3真香,特别是的写法,代码简洁了不少。小寒整理了一份《Vue3实战避坑指南》,把我踩过的坑都记录下来了,希望能帮到准备升级Vue3的朋友(tips:最近忙着年终述职,还没完全整理完)。
三、AI编程助手初体验
今年最大的改变可能就是开始用AI编程助手了。刚开始用Cursor的时候觉得挺神奇的,但也踩了不少坑。比如有次它给我生成的代码看起来没问题,结果运行时各种报错,debug了好久才发现是版本兼容问题。
不过慢慢摸索出了一些技巧,现在主要用它来:
- 写一些重复的模板代码
- 帮忙检查代码中可能的问题
- 生成单元测试用例
四、技术分享这点事
今年在CSDN上写的文章没有去年多了,质量上应该有了一点进步。主要是工作中遇到了很多实际问题,解决后都写成了博客分享出来。最受欢迎的是《Java学习路线》系列,可能是因为都是实际问题,直接能用。
记得刚开始写博客时,就是想给自己做个技术笔记,记录学习和开发过程中的点点滴滴。后来慢慢发现,很多我遇到的问题,很多其实也是其他开发者的痛点。于是就更加用心地把解决方案整理成文章,希望能帮助到有需要的朋友。
说实话,坚持写博客真的需要动力,有时候加班到很晚还要写文章,也挺累的。特别是今年项目进度比较紧,经常加班到很晚,写博客的时间确实比较少。但看到评论区有人说我的文章帮助到了他,那种成就感真的很棒!这也是支持小寒继续写下去的动力。
五、明年的小目标
明年准备深入研究几个方向:
- K8s容器编排 - 现在项目越来越多,要学习容器化部署了
- 性能优化 - 最近系统并发量上来了,得研究下如何优化
- 前端工程化 - 打算好好整理下前端构建和部署流程
最后,感谢大家一直以来的支持。小寒会继续分享更多实用的技术文章,也希望和大家一起在技术道路上共同进步!
对了,如果觉得文章有帮助,别忘了点个赞哦~ 😊
评论记录:
回复评论: