# \[ANN\] Smoothers: Collection of basic smoothers and smoother related applications

**URL:** https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687
**Category:** Package Announcements
**Tags:** statistics, smoothing
**Created:** [September 4, 2021, 10:15am UTC](https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687 "2021-09-04T10:15:43Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![viraltux](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/viraltux/32/15236_2.png) [@viraltux](https://discourse.julialang.org/u/viraltux)
#### Post date: [September 4, 2021, 10:15am UTC](https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687/1 "2021-09-04T10:15:43Z")

</div>

In order to learn Julia I began building the package [Forecast](https://github.com/viraltux/Forecast.jl), after familiarizing myself with the language it was just natural to move from adding new models to the package to refactor it so that the package could benefit from some of the great features that Julia has to offer.

In particular, I am going to divide [Forecast](https://github.com/viraltux/Forecast.jl) into several smaller packages since expanding functionality in Julia packages comes natural to the language. The first of these packages is [Smoothers](https://github.com/viraltux/Smoothers.jl).

The package [Smoothers](https://github.com/viraltux/Smoothers.jl) provides a collection of smoothing heuristics, models and smoothing related applications. The current available smoothers and applications are:

- Henderson Moving Average Filter ( **hma** )
- Linear Time-invariant Difference Equation Filter ( **filter** ) - Matlab/Octave
- Locally Estimated Scatterplot Smoothing ( **loess** )
- Seasonal and Trend decomposition based on Loess ( **stl** )
- Simple Moving Average ( **sma** )

![image](https://global.discourse-cdn.com/julialang/original/3X/0/1/01552ad497178930a024170d706c6f2f487ca0f3.png)

**Note** : `Forecast: stl, loess` return exact solutions, the implementation for `Smoothers: stl, loess` are fast (much faster) implementations but still offer the possibility for exact solutions.

---

<div class="post-metadata">

### Author: ![tlienart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlienart/32/7640_2.png) [@tlienart](https://discourse.julialang.org/u/tlienart)
#### Post date: [September 4, 2021, 2:55pm UTC](https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687/2 "2021-09-04T14:55:14Z")

</div>

Cool! I had a quick look at the source code and saw in `filter`:

```julia
    for n in 1:Nx
        for k in 0:M
            @inbounds y[n] += n-k > 0 ? d[k+1]*x[n-k] : T(0.0)
        end
        for k in 1:N
            @inbounds y[n] -= n-k > 0 ? c[k+1]*y[n-k] : T(0.0)
        end
    end

```

([https://github.com/viraltux/Smoothers.jl/blob/56f1c442e204b5111be5ee4b95fad06bb9c67b21/src/filter.jl#L65-L72](https://github.com/viraltux/Smoothers.jl/blob/56f1c442e204b5111be5ee4b95fad06bb9c67b21/src/filter.jl#L65-L72))

I think there’s a few things that can maybe be improved here (just quick thoughts, I may be wrong)

1. inbounds can be applied on the outer loop
2. `T(0.0)` did you mean `zero(T)` ?
3. the branch (`?`) is unnecessary if you do the first loop over `n+1:M` (unless I’m missing something?) similar question for the second loop
4. I think `d` and `x` potentially have different types so there would be a type promotion in the `d[k+1]*x[n-k]` operation a lot of times which is not ideal

The package seems useful, kudos 🙂

---

<div class="post-metadata">

### Author: ![viraltux](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/viraltux/32/15236_2.png) [@viraltux](https://discourse.julialang.org/u/viraltux)
#### Post date: [September 4, 2021, 3:20pm UTC](https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687/3 "2021-09-04T15:20:28Z")

</div>

Thank you @tlienart for having a look at the code, I myself I am learning about how to optimize Julia code and I appreciate your help.

> [@tlienart](#):
>
> inbounds can be applied on the outer loop

Actually using @inbounds didn’t make much of a difference here, I guess Julia was smart enough to already optimize those loops, one question though, do you know if using @inbounds in the outer loop would apply to any sub-loop and any array in those sub-loops?

> [@tlienart](#):
>
> `T(0.0)` did you mean `zero(T)` ?
> 
> I think `d` and `x` potentially have different types so there would be a type promotion in the `d[k+1]*x[n-k]` operation a lot of times which is not ideal

I am promoting the types’ parameters before I used them, I meant` T(0.0)` where `T` is the type of `x` after` a,b,x,si,_ = Base.promote(a,b,x,si,[Base.promote_op(/,B,A)(1.0)])`

> [@tlienart](#):
>
> the branch ( `?` ) is unnecessary if you do the first loop over `n+1:M` (unless I’m missing something?) similar question for the second loop

Yeah, actually I used this formulation because it was easy to test and it was already really fast, I am aware though that if I treat the n-k \>0 values outside the loop I do not need (?).

As a matter of fact, I am pushing some optimizations with higher priority on the original code as we speak (for hma in this case) but thanks for the reminder!

---

<div class="post-metadata">

### Author: ![viraltux](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/viraltux/32/15236_2.png) [@viraltux](https://discourse.julialang.org/u/viraltux)
#### Post date: [September 4, 2021, 3:24pm UTC](https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687/4 "2021-09-04T15:24:02Z")

</div>

Following up on the kind advice on optimization from @tlienart , I wonder if anybody knows of a good tutorial for parallelization on Julia. When I tried @spawn in `loess` (which admits parallelization for each value) it would become slower instead faster.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [September 4, 2021, 3:28pm UTC](https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687/5 "2021-09-04T15:28:46Z")

</div>

> [@viraltux](#):
>
> good tutorial for parallelization

Maybe @tkf’s material [here](https://juliafolds.github.io/data-parallelism/tutorials/quick-introduction/)

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [September 4, 2021, 5:23pm UTC](https://discourse.julialang.org/t/ann-smoothers-collection-of-basic-smoothers-and-smoother-related-applications/67687/7 "2021-09-04T17:23:52Z")

</div>

> [@viraltux](#):
>
> When I tried @spawn in `loess` (which admits parallelization for each value) it would become slower instead faster.

If you’re just spawning one task per data point, this will produce a LOT of scheduling overhead. For this particularly problem it seems likely that `@threads` is the simplest abstraction, the fitting should be similar in duration for each data point, and this macro auto-splits the data into similar sized blocks with N tasks where N = number of OS threads.
