Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我的Rust代码比同等的Python代码长得多,结果是错误的_Rust - Fatal编程技术网

我的Rust代码比同等的Python代码长得多,结果是错误的

我的Rust代码比同等的Python代码长得多,结果是错误的,rust,Rust,当转换为锈蚀时,线的数量会增加,类型会发生很多变化,最糟糕的是,结果是错误的!我不确定我是否做错了什么,或者是否有办法优化它: 主要功能是: fn main() { let series = [ 30, 21, 29, 31, 40, 48, 53, 47, 37, 39, 31, 29, 17, 9, 20, 24, 27, 35, 41, 38, 27, 31, 27, 26, 21, 13, 21, 18, 33, 35, 40, 36, 22, 2

当转换为锈蚀时,线的数量会增加,类型会发生很多变化,最糟糕的是,结果是错误的!我不确定我是否做错了什么,或者是否有办法优化它:

主要功能是:

fn main() {
    let series = [
        30, 21, 29, 31, 40, 48, 53, 47, 37, 39, 31, 29, 17, 9, 20, 24, 27, 35, 41, 38, 27, 31, 27,
        26, 21, 13, 21, 18, 33, 35, 40, 36, 22, 24, 21, 20, 17, 14, 17, 19, 26, 29, 40, 31, 20, 24,
        18, 26, 17, 9, 17, 21, 28, 32, 46, 33, 23, 28, 22, 27, 18, 8, 17, 21, 31, 34, 44, 38, 31,
        30, 26, 32,
    ];

    triple_exponential_smoothing(&series, 12, 0.716, 0.029, 0.993, 24);
}
三重指数平滑
调用我测试过的另外两个函数,它们给出了正确的结果:

fn initial_trend(series: &[i32], slen: i32) -> f32 {
    let mut sum = 0.0;
    for i in 0..slen as usize { // in Python: for i in range(slen)
        sum += (series[i + slen as usize] as f32 - series[i] as f32) / slen as f32;
    }
    return sum / slen as f32;
}
这是Python代码的转换:

def初始趋势(系列,slen):
总和=0.0
对于范围内的i(slen):
总和+=浮点(系列[i+slen]-系列[i])/slen
返回金额/slen
#>>>初始趋势(系列,12)
# -0.7847222222222222
第二个是:

fn initial_seasonal_components(series: &[i32], slen: i32) -> Vec<f32> {
    let mut seasonals = Vec::new();
    let n_seasons = series.len() as i32 / slen;
    // # compute season averages
    let season_chunks = series //season_averages
            .chunks(slen as usize)
            .collect::<Vec<_>>();
    let season_averages = season_chunks
        .iter()
        .map(|chunk| chunk.iter().sum::<i32>() as f32 / chunk.len() as f32)
        .collect::<Vec<f32>>();
    // # compute initial values
    for i in 0..slen as usize {
        let mut sum_of_vals_over_avg = 0.0;
        for j in 0..n_seasons as usize {
            sum_of_vals_over_avg +=
                series[i + j * slen as usize] as f32 - season_averages[j] as f32;
        }
        seasonals.push(sum_of_vals_over_avg / n_seasons as f32);
    }
    return seasonals;
}
此函数中似乎存在错误:

fn triple_exponential_smoothing(
    series: &[i32],
    slen: i32,
    alpha: f32,
    beta: f32,
    gamma: f32,
    n_preds: i32,
) {
    let mut result: Vec<f32> = Vec::new();
    let mut seasonals = initial_seasonal_components(&series, slen);
    println!("The seasonalities are: {:#?}", seasonals);
    let mut smooth = 0.0;
    let mut trend = 0.0;
    // for i in range(len(series)+n_preds):
    for i in 0..(series.len() + n_preds as usize) as usize {
        match i {
            0 => {
                // # initial values
                smooth = series[0] as f32;
                trend = initial_trend(&series, slen);
                println!("The initial_trend is: {:#?}", trend);
                result.push(series[0] as f32);
            }
            i if i >= series.len() => {
                // # we are forecasting
                let m = i - series.len() + 1;
                result.push(
                    (smooth as usize + m * trend as usize) as f32 + seasonals[i % slen as usize],
                )
            }
            _ => {
                let val = series[i];
                let last_smooth = smooth;
                smooth = alpha * (val as f32 - seasonals[i % slen as usize])
                    + (1.0 - alpha) * (smooth + trend);
                trend = beta * (smooth - last_smooth) + (1.0 - beta) * trend;
                seasonals[i % slen as usize] = gamma * (val as f32 - smooth)
                    + (1 - gamma as usize) as f32 * seasonals[i % slen as usize];
                result.push(smooth + trend + seasonals[i % slen as usize]);
            }
        }
    }
    println!("The forecast is: {:#?}", result);
}


我非常感谢您对优化代码和修复错误的任何评论。

在Rust中,您一直在将所有内容转换为
usize

(1 - gamma as usize) as f32
如果您考虑这个问题,
(1-gamma as usize)
只能是
0
1
,具体取决于
gamma
的值。如果改为

(1.0 - gamma) as f32
也会改变

(smooth as usize + m * trend as usize) as f32

然后得到与Python中相同的结果


至于性能,这看起来是正确的,但是您可以引入一些临时变量来避免一直重新计算相同的内容(尽管优化器应该会有所帮助)。Rust的默认编译模式是debug,请务必切换到基准版本。

我在这里发布了我收到的最佳评论和答案,希望对其他人有用:

尽量减少代码中“as”强制转换的数量(可能减少到零)。进入()/from()并尝试使用\u from()帮助

尝试用迭代器替换一些原始循环

triple_Indonential_smoothing函数的一些参数在调用点很容易混淆,因为Rust当前没有命名参数。为了避免这个问题,您可以尝试在结构/元组中打包一些参数

在函数末尾使用“return”并不是什么惯用法

另外,值得注意的是,在Python中,浮点类型是双浮点,在Rust中是f64。这可能会导致精度上的微小差异,尽管可能没有什么大的差异

替换矿井的功能代码如下所示:

fn main(){
let级数=[
30,21,29,31,40,48,53,47,37,39,31,29,17,9,20,24,27,35,41,38,
27,31,27,26,21,13,21,18,33,35,40,36,22,24,21,20,17,14,17,19,
26,29,40,31,20,24,18,26,17,9,17,21,28,32,46,33,23,28,22,27,
18,8,17,21,31,34,44,38,31,30,26,32];
三重指数平滑(和系列,12,0.716,0.029,0.993,24);
}
fn初始趋势(系列:&[i32],slen:usize)->f32{
series[…slen].iter().zip(&series[slen..)
.map(|)(&a,&b)|(b为f32-a为f32)/slen为f32)。总和:()/slen为f32
}
fn初始季节性组件(系列:&[i32],slen:usize)->Vec{
设n_seasures=series.len()/slen;
//#计算季节平均值
让季节平均值=系列//季节平均值
.区块(slen)
.map(| chunk | chunk.iter().sum::()作为f32/chunk.len()作为f32)
收集::();
//#计算初始值
(0..slen).map(| i |{
设平均值上的值之和=0.0;
对于0..n_季节中的j{
平均值+上的数值之和=系列[i+j*slen]作为f32-季节平均值[j]作为f32;
}
按f32计算的各季平均值之和
}).collect()
}
fn三重指数平滑(系列:&[i32],slen:usize,α:f32,β:f32,
gamma:f32,n_preds:usize){
让mut result:Vec=Vec::new();
设mut季节=初始季节分量(&系列,slen);
println!(“季节性为:{:#?}”,季节性);
让mut平滑=0.0;
让mut趋势=0.0;
对于0中的i..(series.len()+n_preds){
比赛一{
0=>{/#初始值
平滑=系列[0]为f32;
趋势=初始趋势(&系列,slen);
println!(“最初的趋势是:{:},趋势);
结果推送(系列[0]为f32);
},
如果我>=series.len()=>{/#我们正在预测
设m=i-级数.len()+1;
结果。推动((平滑+m为f32*趋势)+季节性[i%slen])
},
_ => {
设val=级数[i];
让最后一个平滑=平滑;
平滑=α*(val为f32-季节性[i%slen])+
(1.0-α)*(平滑+趋势);
趋势=β*(平滑-最后一次平滑)+(1.0-β)*趋势;
季节性[i%slen]=伽马*(val为f32-平滑)+
(1.0-伽马)*季节性[i%slen];
结果:推动(平稳+趋势+季节性[i%slen]);
}
}
}
println!(“预测为:{:#?}”,结果);
}

考虑……的最小方面。。。。这里有大量的代码…当你施放东西时要更加小心。
(smooth + m as f32 * trend)
fn main() {
    let series = [
        30,21,29,31,40,48,53,47,37,39,31,29,17,9,20,24,27,35,41,38,
        27,31,27,26,21,13,21,18,33,35,40,36,22,24,21,20,17,14,17,19,
        26,29,40,31,20,24,18,26,17,9,17,21,28,32,46,33,23,28,22,27,
        18,8,17,21,31,34,44,38,31,30,26,32];

    triple_exponential_smoothing(&series, 12, 0.716, 0.029, 0.993, 24);
}

fn initial_trend(series: &[i32], slen: usize) -> f32 {
    series[..slen].iter().zip(&series[slen..])
        .map(|(&a, &b)| (b as f32 - a as f32) / slen as f32).sum::<f32>() / slen as f32
}

fn initial_seasonal_components (series: &[i32], slen: usize) -> Vec<f32> {
    let n_seasons = series.len() / slen;
    // # compute season averages
    let season_averages = series //season_averages
        .chunks(slen)
        .map(|chunk| chunk.iter().sum::<i32>() as f32 / chunk.len() as f32)
        .collect::<Vec<f32>>();
    // # compute initial values
    (0..slen).map(|i| {
        let mut sum_of_vals_over_avg = 0.0;
        for j in 0..n_seasons {
            sum_of_vals_over_avg += series[i + j * slen] as f32 - season_averages[j] as f32;
        }
        sum_of_vals_over_avg / n_seasons as f32
    }).collect()
}

fn triple_exponential_smoothing(series: &[i32], slen: usize, alpha: f32, beta: f32,
                                gamma: f32, n_preds: usize) {
    let mut result: Vec<f32> = Vec::new();
    let mut seasonals = initial_seasonal_components(&series, slen);
    println!("The seasonalities are: {:#?}", seasonals);
    let mut smooth = 0.0;
    let mut trend = 0.0;

    for i in 0..(series.len() + n_preds) {
        match i {
            0 => {  // # initial values
                smooth = series[0] as f32;
                trend = initial_trend(&series, slen);
                println!("The initial_trend is: {:#?}", trend);
                result.push(series[0] as f32);
            },
            i if i >= series.len() => {  // # we are forecasting
                let m = i - series.len() + 1;
                result.push((smooth + m as f32 * trend) + seasonals[i % slen])
            },
            _ => {
                let val = series[i];
                let last_smooth = smooth;
                smooth = alpha * (val as f32 - seasonals[i % slen]) +
                    (1.0 - alpha)*(smooth + trend);
                trend = beta * (smooth - last_smooth) + (1.0 - beta) * trend;
                seasonals[i % slen] = gamma * (val as f32 - smooth) +
                    (1.0 - gamma) * seasonals[i % slen];
                result.push(smooth + trend + seasonals[i % slen]);
            }
        }
    }
    println!("The forecast is: {:#?}", result);
}