Python绘制sigmoid与tanh曲线:公式、复现与避坑全指南

发布时间:2026/10/18 6:35:43
Python绘制sigmoid与tanh曲线:公式、复现与避坑全指南 简介一份面向深度学习和神经网络初学者的PDF文档系统讲解Sigmoid与Tanh激活函数的可视化绘制方法。内容基于Python的matplotlib和numpy库以逐行代码注释的方式先分开演示两种函数的单独绘制再介绍利用数学关系将二者合并在同一张图中的技巧帮助读者直观理解非线性变换和函数形态差异。文档还简要讨论了Sigmoid在零附近梯度较小、可能引发梯度消失以及Tanh对称性更好等实用知识点适合入门阶段结合代码动手实践。无论是完成机器学习课程作业还是自行尝试小实验都能从中获得清晰的实现思路代码中涉及坐标轴位置调整、刻度设置等常见绘图细节也有说明。资源为单个PDF文件大小仅119KB便于下载阅读目前已有4114人学习浏览是快速上手激活函数绘图与基础理论的实用参考。1. 为什么画sigmoid和tanh这种基础函数反而成了最容易翻车的第一步很多刚接触深度学习的小白都经历过类似的场景数学课上明明背过sigmoid和tanh的公式也觉得“这有什么好画的”可一打开编辑器却不知道该从哪一行写起。更常见的是照着网上代码敲完出来的图要么是一条竖直的线要么是一条横在中间的直线甚至整个坐标轴上都找不到曲线。你盯着屏幕怀疑自己把公式抄错可实际上问题往往出在输入的x没有生成、函数返回类型不对、或者数值溢出变成了inf和nan。这份笔记要做的就是一件事把sigmoid和tanh的绘制过程拆到每一行代码都能看懂。我们既会分开画也会合起来画还会把那些让新手反复改代码的隐藏问题像排雷一样一根根指出来。如果你正准备用Python把这些激活函数画进笔记、论文或教学PPT里又不想在绘图细节上浪费半天时间这篇就是为你准备的。它不追求花哨的可视化技巧只求让你照着写一遍就能得到干净、准确、可以放进任何场合的曲线图。2. 手动画出sigmoid和tanh函数定义与绘图准备2.1 从数学公式到numpy代码sigmoid与tanh的定义逻辑先把两个函数的数学形式摆出来。sigmoid的定义是 σ(x) 1 / (1 e^(-x))输出范围永远在0到1之间。tanh的定义是 tanh(x) (e^x - e^(-x)) / (e^x e^(-x))输出范围是-1到1。很多刚上手的同学会选择直接打开计算器输入公式去验证几个点然后再写代码但这样做容易忽略一个关键差异sigmoid关于点(0, 0.5)中心对称tanh关于原点(0, 0)中心对称。这个差异在画图时直接表现为两条曲线的位置也是后面判断绘制是否正确的重要依据。在Python里实现这两个公式最常见的写法是使用numpy的exp函数。下面这一段代码展示了两种定义方式第一种是严格按照数学公式做四则运算第二种是调用numpy内置的tanh方法。两种写法在x取值比较温和时结果一致但一旦x跑到十几甚至更大的数值第一种写法就可能出现数值不稳定的问题。import numpy as np # 严格照搬数学公式的定义方式 def sigmoid_naive(x): return 1 / (1 np.exp(-x)) def tanh_naive(x): # 这种写法在x绝对值较大时会溢出 return (np.exp(x) - np.exp(-x)) / (np.exp(x) np.exp(-x)) # 数值上更稳定的简化写法 def tanh_stable(x): # exp(2x)的形式避免同时计算exp(x)和exp(-x) # 当x为正数且很大时exp(-x)接近0不会产生无穷大 return (1 - np.exp(-2 * x)) / (1 np.exp(-2 * x)) # 直接用numpy内置函数性能和稳定性最好 def tanh_builtin(x): return np.tanh(x)这段代码里的逻辑说明sigmoid_naive里先对x取负再求exp然后加1取倒数每一步对应一个数学运算符tanh_naive则同时计算了e^x和e^(-x)当x为正数且大于50时exp(x)会超过1e21而exp(-x)接近0两者相减再相加分子分母都趋向于原来的exp(x)虽然理论结果会接近1但中间产生的浮点数可能已经触发numpy的溢出警告。至于参数说明这里重点关注两点第一np.exp接受numpy数组所以这些函数可以直接接收np.linspace生成的一整组x而不用写for循环第二np.tanh内部用更稳健的算法实现对小白来说优先使用np.tanh即可它不会让你处理奇怪的数值警告。2.2 绘制sigmoid曲线的第一版可复现代码有了函数定义接下来就可以画第一条曲线。很多教程喜欢一次性把三四十行代码甩出来然后说“复制运行就能看到结果”但这对小白并不友好因为你根本不知道哪一步在做什么。我习惯的做法是先把最核心的三行写出来生成x轴数据计算y值用plot画出曲线。然后在这三行的基础上逐步添加坐标轴标签、网格和图例。下面这段代码是sigmoid曲线绘制的完整版本每一行旁边都留了注释方便你对照着看。import numpy as np import matplotlib.pyplot as plt # 1. 生成x轴数据 # linspace用来产生从-10到10之间均匀分布的500个点 # 点数越多曲线越光滑但500对于sigmoid来说完全够用 x np.linspace(-10, 10, 500) # 2. 计算对应的y值 # 将整个x数组传入sigmoid_naive函数得到同样长度的y数组 y_sigmoid sigmoid_naive(x) # 3. 创建绘图窗口并设置尺寸单位是英寸 fig, ax plt.subplots(figsize(8, 5)) # 4. 绘制曲线 # label参数用于后续显示图例linewidth控制线条粗细默认是1.5 ax.plot(x, y_sigmoid, labelsigmoid, linewidth2.5) # 5. 添加水平参考线在y等于0.4和0.6的位置画虚线 # 这能帮助我们直观看出曲线是否关于0.5对称 ax.axhline(0.5, colorgray, linestyle--, linewidth0.8, alpha0.7) # 6. 坐标轴与标题 ax.set_xlabel(x) ax.set_ylabel(sigmoid(x)) ax.set_title(Sigmoid Activation Function) # 7. 显示网格alpha让网格颜色淡一点看起来不刺眼 ax.grid(True, alpha0.3) # 8. 显示图例并放置在右上角 ax.legend(locupper right) # 9. 展示图形 plt.show()这段代码的逻辑说明第一步用linspace生成一个包含500个元素的一维数组范围从-10到10。第二步调用函数时numpy会对数组里的每一个元素执行相同的运算最终y_sigmoid也是一个500个元素的数组两者的形状完全一致这是plot能正确画出连续曲线的根本前提。第三步创建的fig和ax分别代表整个画布和画布上的一个坐标系使用这种面向对象写法比直接用plt.plot更灵活后面增加子图时会很方便。参数说明中有三个值得你根据需求调整x的范围越大曲线两端的平台部分越明显但中心区域的变化会被压缩点数num在300以内时曲线会略带折线感我一般用500或800linewidth则完全看个人审美打印到论文里通常建议早1.5到2.5之间。如果你运行后看到图窗里没有任何线条请先检查y_sigmoid是不是全为同一个值那往往意味着输入x数组没有正确生成值而是被当成了一个标量。2.3 绘图前的数据检查shape、dtype与x的取值范围绘图报错和画错这两件事根因往往不在plot函数本身而在数据的形状和类型上。这是个经验问题不是理论问题。很多小白在写代码时习惯先乱敲一通等到画出离谱的图像再回头找bug效率极低。更高效的做法是在调用plot之前先用几行代码确认三个信息x和y的长度是否相等、数据类型是否为浮点数、以及x的范围是否符合预期。# 检查数组形状 print(x shape:, x.shape) # 期望输出 (500,) print(y_sigmoid shape:, y_sigmoid.shape) # 期望输出 (500,) # 检查数据类型 print(x dtype:, x.dtype) # 期望输出 float64 print(y dtype:, y_sigmoid.dtype) # 期望输出 float64 # 检查数值范围 print(x range:, x.min(), to, x.max()) # 期望 -10.0 to 10.0 print(y range:, y_sigmoid.min(), to, y_sigmoid.max()) # 期望接近0和1逻辑说明shape一旦对不上plot会直接抛错或者产生一条奇怪的线段dtype若为int则linspace的精度会受影响极端情况下y值会变成离散的一串阶梯x范围如果过窄比如从-1到1曲线会只显示中间最陡峭的一段看起来不像教科书里的完整sigmoid。这一小步检查可以让你的调试时间缩短一大半。另外这里的参数说明也很直白x.shape返回的是元组打印时看到(500,)表示一维数组如果是(500,1)plot仍然能运行但后续操作容易踩shape不匹配的坑。我始终建议在写绘图代码时把这种print检查留在代码里等图形确认无误后再删除它们是你的临时仪表盘。3. 把tanh也画出来分开画与合起来画的完整实现3.1 同样用numpy计算tanh两种算式的数值稳定性对比tanh在数学公式上看着和sigmoid有点相似但实际画起来需要注意一个非常隐蔽的问题x取到较大绝对值时e^x和e^(-x)的差距会指数级拉大。如果按最原始的公式“先算分子分母再相除”你可能会在控制台看到numpy的RuntimeWarning提示“overflow encountered in exp”然后图片里出现一条断裂的曲线。为了帮你看清这个问题我们可以做一个小实验分别用两种方式去计算x等于100时的tanh值。import numpy as np x_test 100.0 # 方式一原始公式 with np.errstate(overignore): # 临时忽略溢出警告方便观察结果 result_naive (np.exp(x_test) - np.exp(-x_test)) / (np.exp(x_test) np.exp(-x_test)) # 方式二利用1 - exp(-2x)的形式变形 result_stable (1 - np.exp(-2 * x_test)) / (1 np.exp(-2 * x_test)) # 方式三调用内置函数 result_builtin np.tanh(x_test) print(naive result:, result_naive) # 大概率是 nan 或者 inf print(stable result:, result_stable) # 接近 1.0 print(builtin result:, result_builtin) # 同样接近 1.0这个演示的逻辑说明原始公式在x趋向正无穷时e^x会变得极大而e^(-x)趋近于0分子分母实际上都约等于e^x两个极大或极小的数相除浮点数精度不够就会输出nan。第二种写法把分子分母同时除以e^x化简成用e^(-2x)表达的形式当x为正数且很大时e^(-2x)会自然落到可以精确表示的范围内。第三种直接调np.tanh是推荐方案它由底层数学库实现兼顾速度和精度。参数说明里有个小细节值得记住np.errstate是临时上下文管理器它并不修复数值问题只是让警告暂时不显示方便你观察程序是否真的溢出。这只适合做实验实际绘图时不要依赖这种方式来掩盖问题因为得到的nan一旦进入绘图数据整条曲线都会消失。现在你应该明白为什么我建议像下面这样定义安全的tanh函数供绘图使用因为它能承受更极端的数据范围让你的图看起来更完整。3.2 分开画两张图Figure对象与人工控制画布分开画就是sigmoid和tanh各占一个独立的图形窗口或各占一个图片文件。这种需求在写教材、做对比实验时很常见你要把两张图分别插入到文档的不同位置。最容易翻车的点在于连续执行两次plt.show()时第一次弹出的窗口可能会被立即覆盖导致你只看到第二张图。要解决这个问题需要用figure编号或保存图片的方式来做。import matplotlib.pyplot as plt # 第一张图sigmoid # figsize控制整张图的宽和高单位是英寸 plt.figure(1, figsize(7, 4)) plt.plot(x, y_sigmoid, colorblue, linewidth2.5) plt.xlabel(x) plt.ylabel(sigmoid(x)) plt.title(Sigmoid) plt.grid(alpha0.3) # 保存图片到当前目录dpi控制分辨率300适合打印 plt.savefig(sigmoid_curve.png, dpi300) # 第二张图tanh # 重新利用y数组但重新计算tanh的y值 y_tanh np.tanh(x) plt.figure(2, figsize(7, 4)) plt.plot(x, y_tanh, colorred, linewidth2.5) plt.xlabel(x) plt.ylabel(tanh(x)) plt.title(Tanh) plt.grid(alpha0.3) plt.savefig(tanh_curve.png, dpi300) # 显示所有已经创建的图形窗口 plt.show()这段代码的逻辑是先用plt.figure(1)创建第一个图像对象之后的plot、xlabel等操作都会作用到这个图像上紧接着创建plt.figure(2)当前绘图目标切换到第二个图。savefig会把图保存成文件这样即使之后又画了别的图前面的成果也已经留在磁盘上了。最后调用show时两个窗口都会弹出来不会互相覆盖。参数说明figure的第一个参数是编号只要编号不同就可以同时存在多个图。figsize是两个元素的元组宽度在前高度在后。dpi是分辨率默认约为100文档插图惯用300甚至600如果只是屏幕上看看100到150就足够了。还有一点值得注意每次调用figure之后后续的plt语句都会附着到最新创建的图上如果中间切回figure(1)继续操作那之后再执行figure(2)会新建另一个图而不是回到原来的第二张图。3.3 合起来画的三种姿势subplot并排、overlay叠画与归一化对比分开画虽然清楚但在很多对比场景下把两条曲线放进同一张图或者并排放在同一张图中更直观。这里我介绍三种可以按需选择的合起来画法。第一种是subplot并排本质是把一张画布拆成两个区域左边画sigmoid右边画tanh。第二种是overlay叠画把两条曲线画在同一个坐标系中用颜色和图例区分。第三种是归一化对比把sigmoid和tanh都映射到0到1的范围后再叠画这种适合分析两者斜率变化的相似性。我先给出subplot和overlay的完整代码。# 方式一subplot并排 fig, (ax1, ax2) plt.subplots(1, 2, figsize(12, 4)) # 左边sigmoid ax1.plot(x, y_sigmoid, colorblue, linewidth2.5) ax1.set_title(Sigmoid) ax1.set_xlabel(x) ax1.set_ylabel(sigmoid(x)) ax1.grid(alpha0.3) # 右边tanh ax2.plot(x, y_tanh, colorred, linewidth2.5) ax2.set_title(Tanh) ax2.set_xlabel(x) ax2.set_ylabel(tanh(x)) ax2.grid(alpha0.3) # 自动调整子图之间的间距避免标题重叠 plt.tight_layout() plt.savefig(sigmoid_tanh_subplot.png, dpi300) plt.show()# 方式二overlay叠画 plt.figure(figsize(8, 5)) plt.plot(x, y_sigmoid, labelsigmoid, colorblue, linewidth2.5) plt.plot(x, y_tanh, labeltanh, colorred, linewidth2.5) plt.axhline(0, colorblack, linewidth0.8) # 画一条y0的参考线 plt.xlabel(x) plt.ylabel(value) plt.title(Sigmoid vs Tanh) plt.legend(locupper left) plt.grid(alpha0.3) plt.savefig(sigmoid_tanh_overlay.png, dpi300) plt.show()逻辑说明subplots(1, 2)返回一个包含两个Axes对象的数组ax1和ax2分别代表左右两个坐标系所有针对ax1的绘图指令只会作用于左图。这样之后想单独调整左边某个细节也不会影响右边。overlay方式的本质是在同一个坐标系中多次调用plot每次调用相当于在同一块画布上叠一层图层matplotlib会按照调用顺序绘制后画的曲线会覆盖先画的曲线所以一般把sigmoid放在前tanh放在后颜色深浅搭配好。参数说明里有一个容易被忽略的关键参数legend的loc。当两条曲线都处于单调增长状态时sigmoid在0到1区间、tanh在-1到1区间上图左侧会因tanh起始值更低而空出空间所以locupper left是安全选择如果你画的是自己修改过的函数图例位置就要根据曲线实际走向调整。关于subplot的布局subplots(2, 1)是上下排列subplots(1, 3)是一行三个图你只需要记住第一个数是行数、第二个数是列数。做个不需要思考的选择题对比sigmoid和tanh用一行两列最舒服因为横轴统一x方向可对齐。4. sigmoid和tanh绘图的避坑指南画得不顺的5个常见原因4.1 现象一曲线变成一条竖线x轴数据顺序乱了【现象】图像里出现一条笔直的竖线从图底延伸到图顶数学上完全解释不通。【原因】最常见的是x数组没有形成单调递增的有序序列比如你用列表直接拼了几个值或者对x做了sort之后又把原来的顺序弄丢了。另一种可能是x的取值跨度太大而y的显示范围又被自动缩放得很大曲线在视觉上被“拉伸”成了一条接近竖直的线比如x从-1000画到1000中间核心区域的变化被平台区压缩。【解决】先用sort保证x有序x np.sort(np.linspace(-10, 10, 500))。再把x范围缩小到-10到10之间这个区间足够呈现出sigmoid和tanh的全部特征。绘图时手动固定y轴也行用plt.ylim(-0.1, 1.1)给sigmoid留一点边距曲线看起来会更舒服。4.2 现象二图像变成一条水平直线数值溢出被numpy警告【现象】曲线应该有的S形轮廓完全消失取而代之的是一条平直的水平线控制台还有RuntimeWarning。【原因】数值溢出导致的inf或nan会让plot无法正常绘制。x过大时e^(-x)转化为0而exp(x)变为inf数学上sigmoid应该趋近1但程序拿到inf除以inf结果就成了nan整个曲线断掉或拉平。【解决】不要用原始公式硬算极端值。改用np.tanh和稳定的sigmoid写法1 / (1 np.exp(-x))其实已经比较稳定因为exp(-x)在x很大时不会溢出成正无穷。如果还不放心可以把x的区间控制在-50到50以内这样既保留曲线两端的平坦特征又不会触碰浮点数的极限。4.3 现象三用了plt.show()但绘图窗口一闪而过【现象】在命令行或脚本里运行代码窗口瞬间出现又立刻消失根本来不及看清曲线。【原因】脚本执行完后进程结束图形窗口随之关闭。这在Jupyter Notebook里不是问题但用python xxx.py方式运行时就会碰到。【解决】在show之前调用plt.savefig(figure.png)把图存到文件然后从文件里查看或者打开交互模式在代码前加上plt.ion()这样脚本结束后图窗仍然停留在屏幕上。对小白来说我的建议是养成先savefig再show的习惯图和文件都能拿到也方便后续直接用图像查看器放大检查。4.4 现象四中文标题和坐标轴显示成方块乱码【现象】title和label里的中文全变成了一个个方框英文和数字正常。【原因】matplotlib默认字体不包含中文字符系统找不到合适字体时只能用方框占位。【解决】在绘图前指定中文字体常见写法是用plt.rcParams[font.sans-serif] [SimHei]。如果你用的是没有SimHei的环境可以安装所需字体或改成英文标签。最省事的方案是直接使用英文坐标轴说明因为sigmoid和tanh本来就是国际通用词在论文场景下英文标签反而更常见。4.5 现象五两组曲线在同一张图里被同一颜色覆盖无法区分【现象】在overlay叠画时两条曲线颜色一模一样眼睛完全分辨不出哪条是sigmoid哪条是tanh。【原因】没有为第二次plot指定新颜色matplotlib默认颜色循环在第二次调用时会换色但如果代码里手动设置了相同的color或者颜色序列恰好撞车就会覆盖。【解决】显式指定颜色比如sigmoid用蓝色、tanh用红色同时加上linestyle区分比如一个实线、一个虚线这样即使打印成黑白文档也能分辨。具体到本次代码写上colorblue, linestyle-和colorred, linestyle--即可。图例label也要记得写清楚否则依然要靠猜。5. 从“能画”到“画得能放进论文”三处让图变专业的细节画出一条sigmoid曲线是基本操作但如果你要把它放进报告、课程作业、甚至学术论文里就得多留意三个细节。第一个细节是参考线和高亮关键点。sigmoid在x0处取值为0.5tanh在x0处取值为0这两个点是它们的中心对称点也是提问率最高的关键位置。用ax.scatter([0], [0.5], colorgreen, zorder5)突出这个点并在旁边用ax.annotate标注“(0, 0.5)”一下就能让读者抓住曲线特征。第二个细节是图例与线条样式的组合选择。你不可能保证所有人都用彩色显示器阅读所以只依赖颜色区分函数是危险的加一条虚线或者加粗某一条线都远比单靠颜色可靠。我在实际写报告时sigmoid用蓝色实线、tanh用红色虚线而且sigmoid的线宽设为2.5tanh设为2.0双保险。第三个细节是验证自己画的函数是否正确。等到图像画好之后你可以用np.allclose检查数值是否符合预期例如检查tanh在0附近的值是否接近0在±10处是否接近±1。# 验证关键点的函数值是否合理 print(np.tanh(0)) # 期望 0.0 print(sigmoid_naive(0)) # 期望 0.5 print(np.tanh(-10.0)) # 期望接近 -1.0 print(sigmoid_naive(10.0)) # 期望接近 1.0这一段验证的逻辑说明函数值是否正确直接关系到图像的准确性如果np.tanh(0)打印出来不是0说明运行环境或函数定义有误。plot画出来的只是视觉结果数值验证才是判断对错的最终标准。参数说明上np.allclose(a, b, rtol1e-5)可以判断两个数组是否在误差范围内相等如果你想对比自己写的函数和np.tanh的结果用这个函数就对了。我自己的习惯是每次画完这两条曲线都会顺手在代码最后写上三行print验证再盯着坐标轴确认一下对称性。这一步的投入非常少但能拦住大量低级错误。希望这些拆解得够仔细让你绕开学习初期那些不必要的时间损耗。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询