如何在Matplotlib中高亮不同长度列表生成的曲线交点?
直线与Sigmoid函数交点检测及凹包络优化方案
针对直线(仅两个端点)与Sigmoid曲线(大量采样点)的交点检测问题,以及调整上界获取最紧凑凹包络的需求,提供以下可行方案:
方案1:插值直线到Sigmoid采样点集,用符号差法找交点
通过插值将直线扩展到与Sigmoid相同的x采样点上,让两个函数的点列表长度一致,即可使用你熟悉的符号差方法检测交点。
实现代码
import matplotlib.pyplot as plt import numpy as np a = 2.5 x = np.linspace(-5, 5, 100) z = 1 / (1 + np.exp(-x)) # 直线端点定义 x_line = [-5, a] y_line = [1 / (1 + np.exp(5)), 1 / (1 + np.exp(-a))] # 将直线插值到Sigmoid的x采样点上 line_y = np.interp(x, x_line, y_line) # 检测交点:找符号变化的位置 diff = z - line_y cross_indices = np.argwhere(np.diff(np.sign(diff))).flatten() cross_points = [(x[i], z[i]) for i in cross_indices] # 绘图并高亮交点 plt.figure(figsize=(8,5)) plt.plot(x, z, '-b', label='Sigmoid函数') plt.plot(x_line, y_line, 'o--g', label='凹包络', alpha=0.75) for cx, cy in cross_points: plt.scatter(cx, cy, s=100, c='r', marker='*', label='交点') plt.xlabel("x") plt.ylabel("Sigmoid(x)") plt.legend() plt.grid() plt.show()
方案2:数值求解联立方程,高精度找交点
直接定义直线与Sigmoid的误差函数,用数值根查找方法求解交点,不依赖采样点密度,精度更高。
实现代码
import matplotlib.pyplot as plt import numpy as np from scipy.optimize import root_scalar a = 2.5 x = np.linspace(-5, 5, 100) z = 1 / (1 + np.exp(-x)) # 直线端点 x0, x1 = -5, a y0 = 1 / (1 + np.exp(5)) y1 = 1 / (1 + np.exp(-a)) # 直线函数表达式 def line_func(x_val): return y0 + (y1 - y0)/(x1 - x0) * (x_val - x0) # 误差函数:Sigmoid值 - 直线值 def error_func(x_val): sigmoid_val = 1 / (1 + np.exp(-x_val)) return sigmoid_val - line_func(x_val) # 求解交点(在[x0, x1]区间内找根) result = root_scalar(error_func, bracket=[x0, x1], method='brentq') cross_x, cross_y = result.root, line_func(result.root) # 绘图并高亮交点 plt.figure(figsize=(8,5)) plt.plot(x, z, '-b', label='Sigmoid函数') plt.plot([x0, x1], [y0, y1], 'o--g', label='凹包络', alpha=0.75) plt.scatter(cross_x, cross_y, s=100, c='r', marker='*', label='交点') plt.xlabel("x") plt.ylabel("Sigmoid(x)") plt.legend() plt.grid() plt.show()
调整上界获取最紧凑凹包络
要让直线右端点与交点重合,本质是找到直线成为Sigmoid切线的上界a——此时直线仅在左端点和(a, sigmoid(a))处与Sigmoid相交,是最紧凑的凹包络线段。
实现代码(求解最优上界)
import numpy as np from scipy.optimize import root_scalar import matplotlib.pyplot as plt y0 = 1 / (1 + np.exp(5)) # 定义目标函数:切线斜率与直线斜率的误差 def target_func(a): sig_a = 1 / (1 + np.exp(-a)) # Sigmoid在a处的导数(切线斜率) tangent_slope = sig_a * (1 - sig_a) # 左端点到(a, sig_a)的直线斜率 line_slope = (sig_a - y0) / (a + 5) return tangent_slope - line_slope # 求解最优上界a result = root_scalar(target_func, bracket=[0, 5], method='brentq') optimal_a = result.root optimal_y = 1 / (1 + np.exp(-optimal_a)) print(f"最优上界a: {optimal_a:.4f}") print(f"对应Sigmoid值: {optimal_y:.4f}") # 验证绘图 x = np.linspace(-5, 5, 100) z = 1 / (1 + np.exp(-x)) plt.figure(figsize=(8,5)) plt.plot(x, z, '-b', label='Sigmoid函数') plt.plot([-5, optimal_a], [y0, optimal_y], 'o--g', label='最优凹包络', alpha=0.75) plt.scatter(optimal_a, optimal_y, s=100, c='r', marker='*', label='切点/交点') plt.xlabel("x") plt.ylabel("Sigmoid(x)") plt.legend() plt.grid() plt.show()
内容的提问来源于stack exchange,提问作者madhafakha
相关产品推荐
相关产品推荐

