Julia中scipy.optimize.least_squares替代方案及适配方法咨询
Julia 替代 scipy.optimize.least_squares 的实现方案
你可以用 LsqFit.jl 或 Optim.jl 实现和原Python代码一致的功能,以下是具体适配步骤:
1. 安装必要包
首先安装所需Julia包:
using Pkg Pkg.add(["LsqFit", "Optim", "Distances", "DataFrames"])
2. 实现经纬度距离函数
先实现和原Python一致的经纬度距离计算(这里用Haversine距离,若原代码有自定义逻辑可替换):
using Distances function lat_lng_dist(lat::Real, lng::Real, _lat::Vector{<:Real}, _lng::Vector{<:Real}) # 转换为弧度(Haversine距离要求输入为弧度) center = [deg2rad(lng), deg2rad(lat)] # 顺序为(lon, lat) points = hcat(deg2rad.(_lng), deg2rad.(_lat))' # 转换为n×2矩阵,每行对应一个点的(lon, lat) # 计算每个点到中心的距离,返回数组 return haversine.(eachrow(points), Ref(center), Haversine(6371.0)) end
3. 用 LsqFit.jl 实现(对应scipy.least_squares)
LsqFit专门针对最小二乘问题,支持自定义损失函数,完美适配你的需求:
using LsqFit # 定义残差函数:输入参数θ=[lat, lng],返回残差数组 |距离 - 半径| function residual(θ, data) lat, lng = θ _lat, _lng, _radius = data dists = lat_lng_dist(lat, lng, _lat, _lng) return abs.(dists .- _radius) end # 实现predict_center函数,对应原Python逻辑 function predict_center(init_point::Vector{<:Real}, data) # 整理数据为元组(兼容DataFrame或NamedTuple) data_tuple = (data.lat, data.lng, data.radius) # 定义Scipy风格的Cauchy损失函数 cauchy_loss(r; f_scale=1.0) = f_scale^2 * log(1 + (r/f_scale)^2) # 执行拟合,指定Cauchy损失 fit_result = curve_fit(residual, init_point, data_tuple; loss=cauchy_loss) # 返回最优的中心坐标 return fit_result.param end
4. 用 Optim.jl 实现(更灵活的优化选项)
Optim.jl支持更多优化器和自定义目标函数,适合需要更精细控制的场景:
using Optim # 定义目标函数:计算Cauchy损失的总和 function objective(θ, data) lat, lng = θ _lat, _lng, _radius = data dists = lat_lng_dist(lat, lng, _lat, _lng) residuals = abs.(dists .- _radius) # Scipy默认的Cauchy损失参数 f_scale = 1.0 return sum(f_scale^2 * log.(1 .+ (residuals ./ f_scale).^2)) end function predict_center_optim(init_point::Vector{<:Real}, data) data_tuple = (data.lat, data.lng, data.radius) # 使用L-BFGS优化器(和scipy.least_squares默认优化器一致) opt_result = optimize(θ -> objective(θ, data_tuple), init_point, LBFGS()) # 返回最优参数 return Optim.minimizer(opt_result) end
5. 示例使用
using DataFrames # 模拟输入数据(对应原Python的DataFrame) data = DataFrame( lat = [39.9042, 31.2304, 23.1291], lng = [116.4074, 121.4737, 113.2644], radius = [100.0, 200.0, 150.0] ) init_point = [30.0, 115.0] # 调用LsqFit版本 lsq_result = predict_center(init_point, data) println("LsqFit计算的中心坐标: ", lsq_result) # 调用Optim版本 optim_result = predict_center_optim(init_point, data) println("Optim计算的中心坐标: ", optim_result)
关键注意事项
- 原Python代码中
lat_lng_metric_MAE返回残差均值,但scipy的least_squares实际需要残差数组(用于逐元素计算损失),因此Julia实现中调整为返回残差数组或计算损失总和,保证结果一致。 - 若原Python的经纬度距离计算逻辑不同,需修改
lat_lng_dist函数匹配原逻辑。 - Cauchy损失的
f_scale参数可根据需求调整,和Scipy的least_squares中f_scale参数对应。
内容的提问来源于stack exchange,提问作者Maksim
相关产品推荐
相关产品推荐

