news 2026/9/15 8:52:31

[万字博客]机器学习:梯度下降算法(Gradient Descent)与Jupyter的安装、实战[保姆级教程:从安装Acaconda开始手把手教学]

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[万字博客]机器学习:梯度下降算法(Gradient Descent)与Jupyter的安装、实战[保姆级教程:从安装Acaconda开始手把手教学]

目录如下:

1. 问题引入:一个蒙着眼下山的人

2. 梯度下降的相关概念Review

2.1 步长(Learning rate)

2.2 特征(Feature)

2.3 假设函数(Hypothesis Function)

2.4 损失函数(Loss Function)

3. 梯度下降与代价函数结合(一元线性回归)

4. (※很重要)求解损失函数的导数

5. 梯度下降法的推导流程

5.1先决条件:确认优化模型的假设函数和损失函数

5.2算法相关参数初始化

5.3算法过程

6. 计算损失函数

7. 梯度下降法三兄弟:BGD/SGD/MGD

7.1 全梯度下降法(Full Gradient Descent,FG/批量梯度下降 BGD)

7.2 随机梯度下降法(Stochastic Gradient Descent,SGD)

7.3 小批量梯度下降法(Mini-batch Gradient Descent,MGD)

7.4 怎么选batch_size?

7.5 三兄弟对比表

7.6 别忘了学习率!

8. 案例讲解:学生成绩预测(附录有上机实战,从安装Acaconda开始手把手教学)

8.1 案例背景

8.2 数据

8.3 步骤分析

8.4 数据导入

8.5 模型训练和预测

9. 总结

附录:Jupyter的安装与第一个项目实战(Anaconda版)

附1. 选择Anaconda的理由

附2. Anaconda与jupyter安装步骤

附3. 第一个项目:跑通"学生成绩预测"

附4. 跑通验收标准

附5. 常见坑速查表(Anaconda版)


1. 问题引入:一个蒙着眼下山的人

设想一个场景:大雾天,你被蒙住眼睛,站在一座山的半山腰。你的目标是走到山谷最低点——当然,你看不见整个山势,也看不清谷底在哪里。

你能怎么办?

你只能靠脚下的感觉:感受一下脚下哪个方向是下坡,然后朝那个方向迈一步;到了新位置,再感受一下,再迈一步……就这么一步、一步地往下走。虽然你全程都"看不见全局",但只要每一步都在往下走,你最终就能到达谷底。

这个朴素的想法,就是梯度下降(Gradient Descent)的核心思想。

把场景映射到机器学习里:

下山场景机器学习
你的位置模型参数(theta)
山的海拔损失函数(Loss Function)
"下坡的方向"梯度的负方向(最陡下降方向)
每步迈的步子大小学习率(Learning Rate/步长)
山谷最低点损失函数最小值处(最优参数)

机器学习里的"训练模型",本质上就是在不断调整参数,让损失函数越来越小——和蒙眼下山是同一件事。

2. 梯度下降的相关概念Review

在正式推导之前,先复习四个基础概念。

2.1 步长(Learning rate)

步长决定了在梯度下降迭代的过程中,每一步沿梯度负方向前进的长度。用下山的例子,步长就是你当前这一步沿着最陡峭、最易下山的位置走的那一步的长度。

步长太小→走得很慢,半天到不了谷底;

步长太大→一步跨过头,可能在山谷两边来回"弹跳",甚至越走越高(发散)。

2.2 特征(Feature)

特征指的是样本的输入部分。比如有两个"单特征"样本,则第一个样本特征记为,第一个样本输出记为,即数据集为:

推广到一般情况:,其中是样本个数。

2.3 假设函数(Hypothesis Function)

在监督学习中,为了拟合输入样本而使用的函数,记为。比如对于单特征的样本,可以采用如下拟合函数:

其中就是我们要学习的模型参数

2.4 损失函数(Loss Function)

为了评估模型拟合的好坏,我们用损失函数来度量拟合的程度。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。

在线性回归中,损失函数通常为"样本输出和假设函数的差,取平方后的平均数"(均方误差):

为什么是"差值的平方"?因为差可正可负,平方后:

① 全部变成非负,方便比较大小;

② 放大了大误差的惩罚(误差 2 的损失是 4,误差 1 的损失是 1,翻倍不是线性增长)。

至于前面为什么乘 1/(2m)——m是为了取平均,2 是为了后面求导时好约分,属于"数学上的小体贴"。

3. 梯度下降与代价函数结合(一元线性回归)

现在我们手里有两样东西:

梯度下降算法(怎么下山):不断重复直到收敛;

线性回归模型(山长什么样);

把两者结合:梯度下降负责"沿最陡方向下山",而这座"山"就是线性回归的损失函数。每迭代一步,就沿着各自负梯度的方向迈一小步,直到损失函数不再下降,就得到了最优的拟合直线。

这里有一个非常重要的细节:参数要"同时更新"(simultaneously update)

"同时更新"的意思是说:计算新和计算新时,用的都是更新前的旧,而不是先更新、再用新去算。这两者结果完全不同,一定要用临时变量把新值都算好,再一起赋回去。

4. (※很重要)求解损失函数的导数

有了损失函数,梯度下降需要知道每个参数方向上的"坡度",也就是对损失函数求偏导。

我们要分别求。这里用到的数学工具是链式法则(对复合函数求导)。

回忆,所以:

的系数是 1)

的系数是 x)

求导是,再由链式法则:

,2与1/(2m)约分→1/m):

,多乘一个):

把这两个偏导代回梯度下降更新式,算法就可以改写成:

直观理解:是"预测值与真实值的误差"。误差为正(预测大了)→减去一个正数→θ变小;误差为负(预测小了)→减去一个负数→θ变大。所有样本的误差一起平均,决定这一大步往哪走——这就是"用数据修正模型"。

5. 梯度下降法的推导流程

把整套算法串起来:

5.1先决条件:确认优化模型的假设函数和损失函数

比如对于线性回归,假设函数为(多元情形,用于凑出常数项):

写成求和与向量形式更简洁:

对应的损失函数:

5.2算法相关参数初始化

初始化参数(比如全0或随机小值)、算法终止距离δ步长(学习率)

5.3算法过程

确定当前位置损失函数的梯度:(就是第4节求的东西)

当前位置下降一步的距离:

判断是否对于所有的参数,梯度下降的距离都小于δ——如果小于则算法终止,否则进入步骤 ④

更新所有的,对于,其更新表达式如下,更新完毕后再转入步骤①:

不同参数拆开写就是():

......

每个参数都用"自己的那列特征"去加权误差,方向互不干扰、同时更新。

6. 计算损失函数

实际上,损失函数用NumPy几行就能实现:

import numpy as np def computeCost(x, y, theta): inner = np.power(((x * theta.T) - y), 2) # 每个样本的误差平方 return np.sum(inner) / (2 * len(x)) # 全部加起来取平均,再乘 1/2

其中x是特征矩阵(形状m×(n+1),第一列全为1),y是真实标签向量,是参数行向量。x * theta.T就是m个样本的预测值,减去y求平方再平均,就得到了

7. 梯度下降法三兄弟:BGD/SGD/MGD

上面的公式(5.3里的④)里有一个变量——"每次更新用多少个样本?" 根据这个答案的不同,梯度下降分为三兄弟:

7.1 全梯度下降法(Full Gradient Descent,FG/批量梯度下降 BGD)

具体做法:更新参数时使用所有的样本。计算训练集所有样本的误差,对其求和再取平均值作为目标函数。

优点:每步方向是全局最准确的,loss 平滑单调下降,凸函数下能稳定收敛到全局最优。

缺点:每次更新都要在整个数据集上计算所有梯度,速度很慢无法处理超出内存容量限制的数据集不能在线更新模型,即运行过程中不能增加新的样本。

打个比方:BGD像"全员大会决策制"——每走一步,全公司所有员工都要汇报一遍意见,方向绝对靠谱,但开一次会就要等所有人,走得又慢又累。

7.2 随机梯度下降法(Stochastic Gradient Descent,SGD)

具体做法:每次只代入计算一个样本目标函数的梯度来更新权重,再取下一个样本重复此过程,直到损失函数值停止下降或损失函数值小于某个可以容忍的阈值。

优点:每步只需算1个样本,速度飞快;可以边训练边来新样本(在线学习);由于噪声大,反而通常能较好地避免陷入局部最优解

缺点:单样本带来的噪声让路线歪歪扭扭,若遇上噪声则容易陷入局部最优解;最终会在最小值附近来回波动,难以精确收敛到最小值。

打个比方:SGD像"个人拍板制"——一个人说往东就往东,走一步算一步,快是真快,但方向全凭个人感觉,路线歪歪扭扭,到了谷底附近还会来回打转。

7.3 小批量梯度下降法(Mini-batch Gradient Descent,MGD)

具体做法:小批量梯度下降是FG和SG的折中方案,一定程度上兼顾了两者的优点。每次从训练样本集中随机抽取一个小样本集,在这个小样本集上用FG的方式迭代更新权重。

被抽出的小样本集所含样本点的个数称为batch_size通常设置为2的幂次方(如 64、128、256、512),更有利于GPU加速处理。

迭代形式为(从m个样本中选x个样本进行迭代,1<x<m):

两个极端:若 batch_size = 1 →退化为 SGD(每个样本就是一个子集,共m个子集);若 batch_size = m →退化为BGD(只有一个子集 (X, Y))。

打个比方:MGD 像"小组讨论制"——几个代表商量一下方向就走,既不像全员大会那么慢,又不像一个人拍板那么飘,是实际工程中最常用的方案。

三种算法的"下山路线"差异,一张图看懂:

图中蓝色BGD路线平滑稳定直达谷底;紫色SGD路线弯弯绕绕但步伐快;绿色MGD介于两者之间。

关于loss曲线的振荡:

使用BGD,随着迭代次数增加,loss是不断减小的;而使用MGD,随着在不同mini-batch上迭代训练,loss不是单调下降,而是受类似noise的影响出现振荡——比如可能第一个子集是"好子集",而第二个子集恰好包含了一些噪声。但整体趋势是下降的,最终也能得到较低的loss值,出现细微振荡是正常现象:

7.4 怎么选batch_size?

mini-batch size不能设置得太大或太小

总体样本不大时(比如m≤2000),直接使用BGD

m很大时,推荐的mini-batch size为64、128、256、512(2的幂,提高运算速度);

BGD使用所有m个样本,会比较平稳地接近全局最小值,但每次前进的速度有些慢;

SGD每次前进速度很快,但路线曲折、振荡较大,最终会在最小值附近来回波动,难以真正达到最小值处。

7.5 三兄弟对比表

对比项BGD(全梯度)SGD(随机)MGD(小批量)
每次更新用样本数全部m个1个一小批(batch_size)
更新速度较快
路径稳定性平滑稳定曲折颠簸折中(有细微振荡)
loss 曲线单调下降波动大整体下降带振荡
能否在线更新不能
是否易陷入局部最优凸函数收敛全局最优噪声大,通常可跳出局部最优介于两者之间
内存友好度差(需全量数据)
实际应用小数据集(m≤2000)在线学习/超大数据集最常用

7.6 别忘了学习率

不管哪一版梯度下降,都躲不开学习率这个"步子大小"的问题:

太小:稳稳当当,但收敛极慢,训练时间感人;

合适:几步就到谷底附近,效率最高;

偏大:在谷底两边来回震荡,loss反复横跳;

过大:一步跨过山谷,越跳越远,直接发散(损失函数爆炸)。

8. 案例讲解:学生成绩预测(附录有上机实战,从安装Acaconda开始手把手教学)

理论知识到此为止,接下来来看一个完整案例。

8.1 案例背景

我们想用"平时成绩+期末成绩"预测"最终成绩"。用sklearn的线性回归API:

from sklearn.linear_model import LinearRegression # LinearRegression() # LinearRegression.coef_:回归系数

8.2 数据

学生平时成绩期末成绩最终成绩
1808684.2
2828080.6
3857880.1
49090
5868283.2
6829087.6
7788079.4
8929493.4

那么,第4位同学的最终成绩是"?"——这就是要预测的目标。

8.3 步骤分析

机器学习建模的标准五步:1. 获取数据集 → 2. 数据基本处理 → 3. 特征工程 → 4. 机器学习 → 5. 模型评估

8.4 数据导入

x = [[80, 86], [82, 80], [85, 78], [90, 90], [86, 82], [82, 90], [78, 80], [92, 94]] y = [84.2, 80.6, 80.1, 90, 83.2, 87.6, 79.4, 93.4]

8.5 模型训练和预测

# 实例化 API estimator = LinearRegression() # 使用 fit 方法进行训练 estimator.fit(x, y) # 查看回归系数 estimator.coef_ # array([0.3, 0.7]) # 预测:平时 100、期末 80 的同学最终成绩 pred = estimator.predict([[100, 80]]) print(pred) # [86.]

模型的系数是[0.3, 0.7],意味着最终成绩≈0.3×平时成绩+0.7×期末成绩。回看第4位同学:0.3×90 + 0.7×90 = 90,与真实值90完全吻合,说明拟合得很不错。预测"平时100、期末80"的同学→0.3×100 + 0.7×80 = 86,输出正是86.0。

9. 总结

  1. 梯度下降的本质:沿着损失函数下降最快的方向(负梯度)迭代更新参数,直到损失不再下降——蒙着眼下山。
  2. 三个关键角色:损失函数(要爬的山)、学习率(步子大小)、终止条件δ(走多近算到)。
  3. 三兄弟怎么选:数据小用BGD,数据大用MGD(batch_size取2的幂),要在线学习/逃离局部最优可以考虑SGD。
  4. 两个必须小心的坑:学习率太大会发散、太小会龟速;参数必须同时更新。

最后,谢谢恩师陈老师。

如果这篇笔记能帮你把梯度下降讲懂哪怕一点点,欢迎点赞收藏,也欢迎评论区斧正~

接下来,上实战!

附录:Jupyter的安装与第一个项目实战(Anaconda版)

前面把梯度下降的理论和案例都讲完了,纸上谈兵不如动手跑一遍。本文附上用Anaconda安装Jupyter并跑通"学生成绩预测"案例的完整流程(Windows)。

附1. 选择Anaconda的理由

Anaconda是一个"数据科学全家桶"发行版:装好它,Jupyter、numpy等常用库全送,不需要一个一个pip安装,对新手最友好。缺点是安装包比较大(好几个GB哦),但换来的是省心和稳定。

附2. Anaconda与jupyter安装步骤

第1步:下载Anaconda安装包

官网:https://www.anaconda.com/download(国内网络慢的话,用清华镜像:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/,下载最新的Windows x86_64 版exe)。

此处以清华源的Anaconda3-2025.12-2-windows-x86_64.exe为例,进行案例讲解。

第2步:安装

双击exe,跟着我的截图一路Next,注意以下两点以及我图片里标注的项

安装路径建议不放C盘,不要装在带中文和空格的目录

到 "Advanced Options" 这一步:不要勾选 "Add Anaconda3 to my PATH"。勾了容易和电脑里已有的Python环境抢环境变量。不勾也没关系,因为目前我们不用普通CMD启动,用专门的Anaconda Prompt。

勾选项为:

Create shortcuts:创建开始菜单快捷方式——勾上

Register Anaconda3 as the system Python 3.13:把 Anaconda 的 Python 注册为系统默认 Python——勾上(VSCode/PyCharm能自动识别)

Clear the package cache upon completion:装完后清理安装缓存,省磁盘空间——勾上

配置环境变量:

在系统变量里找到Path并双击:

点击新建:

我们要新建四个相关acaconda的环境变量,请替换成自己的实际路径:

Anaconda
Anaconda\Scripts
Anaconda\Library\bin
Anaconda\Library\mingw-w64\bin

配置完成点击确定退出即可。在应用列表里就可以看到Acaconda的身影了!恭喜我们安装好啦!(但是还要验证有没有真的安装好了)

第3步:验证安装

打开开始菜单→找到并打开Anaconda Prompt(这是Anaconda自带终端,会默认进入它的base环境),输入:

conda --version

能显示版本号(如conda 25.x.x)就说明安装成功。

新建虚拟环境:

conda create -n new_env //new_env更换成你的虚拟环境的名字

在创建环境、安装各种库时会有一个确认请求,输入y确认即可:

查看环境列表:

conda env list

切换虚拟环境:

conda activate new_env

退出虚拟环境使用口令conda deactivate。

安装jupyter:

pip install jupyter notebook

安装内核:

pip install ipykernel

注册内核:

python -m ipykernel install --user --name=myenv --display-name="Python (myenv)"

其中:

myenv替换成自己的kernel内核标识符(建议与环境名一致);

引号内的"Python (myenv)"是Jupyter界面里显示的名字,可以随意改成自己喜欢的名字。

输入以下口令可以查看当前所有内核:

jupyter kernelspec list

第4步:启动Jupyter

在Anaconda Prompt里输入:

jupyter notebook

稍等片刻,浏览器会自动打开http://localhost:8888,看到文件列表页面(你的用户名目录)就成功了。

注意:这个Anaconda Prompt窗口不能关,关了网页就打不开了(Jupyter服务是跟着终端走的)。

但是我们发现,目前的文件夹有很多乱七八糟的内容,我们怎样才能给自己弄一个专门用来放code的空文件夹呢?(为了方便管理)

法一:切换启动目录,专门用一个本地文件夹作为Jupyter根目录

目前不建议在C:\Windows\System32运行jupyter,这个是系统目录,容易有权限问题,文件杂乱。

操作步骤:

1.先把当前jupyter服务关掉:在 Anaconda Prompt窗口,按Ctrl+C,输入y关闭jupyter;

2.在电脑D盘/桌面新建一个文件夹,例如D:\jupyter_code(专门存放所有代码);

3.在Anaconda Prompt(现在是study环境)输入命令,切换到这个目录,再重新启动。

D: cd D:\jupyter_code
jupyter notebook

打开网页后,根目录就直接是D:\jupyter_code,干干净净,以后所有代码文件都存在这里。

以后每次打开Anaconda Prompt,只要先执行cd D:\jupyter_code,再启动 jupyter,就直接进入这个专属工作区啦。

法二:但如果不想每次都手动cd切换目录,可以修改jupyter配置,默认打开就进D盘工作文件夹:

关闭 jupyter,在 Anaconda Prompt 输入:

jupyter notebook --generate-config

找到生成的jupyter_notebook_config.py,搜索notebook_dir

修改为:

c.NotebookApp.notebook_dir = 'D:\\jupyter_code'

注意是双反斜杠,去掉前面#注释符号,保存。再重启jupyter就默认打开这个文件夹。

路径看截图高亮引导:(你的路径不一定跟我的一样,但位置是差不多的)

找到这个.py文件并打开呀,搜索notebook_dir:

添加指定内容:

重新启动jupyter notebook,可以发现已经是干干净净的了!

附3. 第一个项目:跑通"学生成绩预测"

所有准备工作做好,我们开始实战了!

在Jupyter文件列表页右上角点New→Python 3(ipykernel)新建一个笔记本,然后把下面代码逐个复制进格子(Cell),每个格子输完按Shift+Enter运行。

Cell 1:验证环境

print("Hello, Jupyter!") import numpy as np print("numpy 版本:", np.__version__)

Cell 2:导入线性回归API

from sklearn.linear_model import LinearRegression

啊呀,报错了:报错是因为当前Jupyter选中的study内核对应的Python环境里没有安装scikit-learn库。

我们保存当前代码退出,重新打开窗口,输入(使用清华源要快一点哦):

pip install scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple --default-timeout=1000

安装完成之后,再重新启动jupyter notebook呀,重新回到code编译之前,记得重启内核(Restart Kernel):

restart之后,所有cell都需要重新运行哦,Jupyter的[数字]代表执行顺序,不是单元格从上到下的顺序!

通过啦!(迈出了具有里程碑的一步!)

Cell 3:准备数据(平时成绩、期末成绩→最终成绩)

x = [[80, 86], [82, 80], [85, 78], [90, 90], [86, 82], [82, 90], [78, 80], [92, 94]] y = [84.2, 80.6, 80.1, 90, 83.2, 87.6, 79.4, 93.4] print("样本数:", len(x))

Cell 4:训练模型

estimator = LinearRegression() estimator.fit(x, y) print("回归系数 coef_:", estimator.coef_)

看到[0.3 0.7]就说明模型学出来——最终成绩 ≈ 0.3×平时 + 0.7×期末,和我们的结论完全一致。

Cell 5:预测

print("第4位同学预测:", estimator.predict([[90, 90]])) # 应接近 90.0 print("新同学预测:", estimator.predict([[100, 80]])) # 应为 86.0

Cell 6(加餐):用numpy手写正文里的损失函数验证参数

import numpy as np def computeCost(x, y, theta): pred = x @ theta inner = np.power((pred - y), 2) return np.sum(inner) / (2 * len(x)) X = np.column_stack([np.ones(len(x)), np.array(x)]) Y = np.array(y) theta = np.array([0.0, 0.3, 0.7]) print("当前损失 J(θ) =", computeCost(X, Y, theta))

Cell 7(加餐):画预测效果图(注意!!要提前下载matplotlib库哦)

pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple --default-timeout=1000

由于matplotlib默认字体DejaVu Sans不支持中文,编译后会产生很多警告,我们提前在绘图代码最开头设置支持中文的字体,再加一行解决负号乱码。

import matplotlib.pyplot as plt # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] #黑体 plt.rcParams['axes.unicode_minus'] = False #负号显示异常问题 pred_all = estimator.predict(x) plt.figure(figsize=(6, 4)) plt.scatter(y, pred_all, color='steelblue', s=40) #s是散点大小 plt.plot([min(y), max(y)], [min(y), max(y)], 'r--', linewidth=2) #linewidth=2红色虚线加粗 plt.xlabel("真实最终成绩", fontsize=11) plt.ylabel("预测最终成绩", fontsize=11) plt.title("学生成绩预测效果", fontsize=12) plt.grid(alpha=0.3) #alpha=0.3浅灰色网格 plt.show()

点越集中在红虚线附近,说明预测越准。

附4. 跑通验收标准

其实同时满足这三点,第一个项目就正式跑通了,我们的任务圆满完成!

1、Cell 4输出coef_[0.3 0.7]

2、Cell 5预测输出[86.]

3、目录里多出一个.ipynb文件(Ctrl+S保存,名字随意,如test1_student_score.ipynb)。

以后每次使用:打开Anaconda Promptjupyter notebook→打开保存的.ipynb或者新建一个继续写。

附5. 常见坑速查表(Anaconda版)

现象原因解决办法
conda不是内部或外部命令普通CMD里没进conda 环境改用开始菜单里的Anaconda Prompt
网页打开但新建时没有Python 3缺ipykernelAnaconda Prompt里pip install ipykernel后重启 Jupyter
8888端口被占用别处已开了一个jupyter notebook --port=8889
关掉终端网页就打不开正常现象,服务随终端退出重新运行jupyter notebook
运行代码报ModuleNotFoundError缺某个库Anaconda Prompt里pip install 库名(必要时使用清华源)后记得在菜单栏Kernel→Restart
想用已有Python跑Jupyter与Anaconda 混用不建议混用;Anaconda自带Python,直接用它的环境即可

结语:理论配实战,才是最快的掌握方式。

希望这篇总结能帮助到你,如有错误或遗漏,欢迎指正交流!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 8:48:41

什么时候不需要MCP

问题 经常看到招聘 JD 上写着 MCP&#xff0c;似乎每个人都要会 MCP 才能做 agent 开发又有人说 MCP 太重了&#xff0c;没什么人用 MCP我们又会看到很多教程说&#xff0c;使用 MCP 统一接口很好用 我们平时看到的教程都是介绍 MCP 是什么&#xff0c;为什么要用 MCP。说了很多…

作者头像 李华
网站建设 2026/9/15 8:45:12

Open UI5日历加载机制与国际化应用实践

1. Open UI5 启动序列中的日历加载机制剖析在Open UI5框架的初始化过程中&#xff0c;loadCalendar.js扮演着关键但常被忽视的角色。这个不到200行的文件位于UI5核心模块的启动序列中&#xff0c;负责处理与区域设置&#xff08;locale&#xff09;相关的日历加载逻辑。不同于其…

作者头像 李华
网站建设 2026/9/15 8:42:10

AI编程时代程序员生存指南:从编码执行者到问题解决者

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 8:41:03

Unity资源管理的三重断裂:引用、生命周期与职责

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 8:40:32

AI辅助老Unity项目WebGL移植:存档失败与内存优化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华