{"id":15063635,"url":"https://github.com/georgeguimaraes/soothsayer","last_synced_at":"2026-01-21T22:02:19.059Z","repository":{"id":255247509,"uuid":"830011211","full_name":"georgeguimaraes/soothsayer","owner":"georgeguimaraes","description":"Elixir library for time series forecasting, inspired by Facebook's Prophet and NeuralProphet","archived":false,"fork":false,"pushed_at":"2024-09-27T00:34:18.000Z","size":93,"stargazers_count":82,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-17T16:48:40.380Z","etag":null,"topics":["elixir","machine-learning","neural-networks","neuralprophet"],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/soothsayer","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/georgeguimaraes.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-17T12:40:03.000Z","updated_at":"2025-04-15T11:39:51.000Z","dependencies_parsed_at":"2024-09-08T18:30:22.960Z","dependency_job_id":"53bb6e49-96af-4417-814e-92a2690c94f2","html_url":"https://github.com/georgeguimaraes/soothsayer","commit_stats":null,"previous_names":["georgeguimaraes/soothsayer"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgeguimaraes%2Fsoothsayer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgeguimaraes%2Fsoothsayer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgeguimaraes%2Fsoothsayer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgeguimaraes%2Fsoothsayer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/georgeguimaraes","download_url":"https://codeload.github.com/georgeguimaraes/soothsayer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250371956,"owners_count":21419692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","machine-learning","neural-networks","neuralprophet"],"created_at":"2024-09-25T00:05:09.100Z","updated_at":"2026-01-21T22:02:19.053Z","avatar_url":"https://github.com/georgeguimaraes.png","language":"Elixir","funding_links":[],"categories":["Machine Learning"],"sub_categories":["Traditional Machine Learning"],"readme":"# Soothsayer 🧙🔮\n\n[![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2Fgeorgeguimaraes%2Fsoothsayer%2Fblob%2Fmain%2Flivebook%2Fsoothsayer_tutorial.livemd)\n\nSoothsayer is an Elixir library for time series forecasting, inspired by Facebook's Prophet and NeuralProphet. It decomposes your time series into interpretable components (trend, seasonality, auto-regression, events) and uses neural networks to learn the patterns.\n\n**Warning:** Soothsayer is currently in alpha stage. The API is unstable and may change at any moment without prior notice. Use with caution in production environments.\n\n## Installation\n\nAdd `soothsayer` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:soothsayer, \"~\u003e 0.1.0\"},\n  ]\nend\n```\n\nThen run `mix deps.get` to install the dependencies.\n\n## Quick Start\n\n```elixir\nalias Explorer.DataFrame\nalias Explorer.Series\n\n# Your data needs two columns: \"ds\" (dates) and \"y\" (values)\ndf = DataFrame.new(%{\n  \"ds\" =\u003e Date.range(~D[2020-01-01], ~D[2022-12-31]),\n  \"y\" =\u003e your_values\n})\n\n# Create and fit the model\nmodel = Soothsayer.new()\nfitted_model = Soothsayer.fit(model, df)\n\n# Make predictions\nfuture_dates = Date.range(~D[2023-01-01], ~D[2023-12-31])\npredictions = Soothsayer.predict(fitted_model, Series.from_list(Enum.to_list(future_dates)))\n```\n\nYou can also get individual components to understand what's driving the forecast:\n\n```elixir\ncomponents = Soothsayer.predict_components(fitted_model, future_dates_series)\n# =\u003e %{combined: ..., trend: ..., yearly_seasonality: ..., weekly_seasonality: ..., ar: ..., events: ...}\n```\n\nTo model special events like holidays or promotions:\n\n```elixir\n# Define events with optional windows (days before/after)\nmodel = Soothsayer.new(%{\n  events: %{\"black_friday\" =\u003e %{lower_window: -1, upper_window: 1}}\n})\n\nevents_df = DataFrame.new(%{\n  \"event\" =\u003e [\"black_friday\", \"black_friday\"],\n  \"ds\" =\u003e [~D[2021-11-26], ~D[2022-11-25]]\n})\n\nfitted_model = Soothsayer.fit(model, df, events: events_df)\n```\n\nClick the \"Run in Livebook\" badge above to try the interactive tutorial, or check the `livebook` directory for examples.\n\n## Features\n\nSoothsayer models time series as a sum of components:\n\n```\ny(t) = trend(t) + seasonality(t) + ar(t) + events(t)\n```\n\nEach component can be enabled or disabled depending on your data.\n\n### Trend\n\nCaptures long-term growth or decline in your data. Enable this when your data has a general upward or downward direction over time.\n\n```elixir\nSoothsayer.new(%{\n  trend: %{enabled: true}  # this is the default\n})\n```\n\nGood for: sales growth, user adoption, gradual temperature changes.\n\n#### Changepoints\n\nBy default, Soothsayer uses piecewise linear trends with automatic changepoint detection. This allows the trend to change slope at multiple points, capturing shifts in growth rate (e.g., a product launch, market change, or policy update).\n\n```elixir\nSoothsayer.new(%{\n  trend: %{\n    changepoints: 10,      # number of potential changepoints (default: 10)\n    changepoints_range: 0.8  # place changepoints in first 80% of data (default: 0.8)\n  }\n})\n```\n\nThe model learns which changepoints matter and how much the slope changes at each one. Setting `changepoints: 0` disables changepoints and uses a simple linear trend.\n\n**Trend regularization** can prevent overfitting when you have many changepoints:\n\n```elixir\ntrend: %{\n  changepoints: 25,\n  regularization: 0.1  # L1 penalty pushes small slope changes toward zero\n}\n```\n\nThis is useful when you're not sure how many changepoints you need. Set more than you think necessary and let regularization prune the unimportant ones.\n\n### Seasonality\n\nCaptures repeating patterns at fixed intervals. Soothsayer supports yearly and weekly seasonality using Fourier terms.\n\n```elixir\nSoothsayer.new(%{\n  seasonality: %{\n    yearly: %{enabled: true, fourier_terms: 6},\n    weekly: %{enabled: true, fourier_terms: 3}\n  }\n})\n```\n\n**Yearly seasonality** captures patterns that repeat every year (holiday shopping, summer peaks, etc). More `fourier_terms` means more flexibility to fit complex seasonal shapes, but also more risk of overfitting.\n\n**Weekly seasonality** captures patterns that repeat every week (weekend dips, Monday spikes, etc). Usually needs fewer fourier terms than yearly.\n\n| fourier_terms | Flexibility | Use when |\n|---------------|-------------|----------|\n| 3 | Low | Simple, smooth seasonal patterns |\n| 6 | Medium | Most cases (default for yearly) |\n| 10+ | High | Complex patterns with sharp peaks |\n\n### Auto-Regression (AR)\n\nCaptures dependencies on recent values. Enable this when today's value depends on yesterday's (or the last few days). This is common in financial data, sensor readings, and anything with momentum.\n\n```elixir\nSoothsayer.new(%{\n  ar: %{\n    enabled: true,\n    lags: 7           # use the last 7 values to predict the next one\n  }\n})\n```\n\n**Choosing `lags`:** Start with the natural cycle of your data. For daily data with weekly patterns, try 7. For data with monthly patterns, try 30. You can also look at autocorrelation plots to see how many lags are actually useful.\n\n#### Deep AR-Net\n\nFor non-linear autoregressive patterns, you can add hidden layers:\n\n```elixir\nar: %{\n  enabled: true,\n  lags: 7,\n  layers: [32, 16]  # two hidden layers with ReLU activation\n}\n```\n\nUse this when the relationship between past and future values is complex. For simple linear relationships, leave `layers` empty (the default).\n\n#### Regularization\n\nL1 regularization pushes AR weights toward zero, which prevents overfitting when you have many lags:\n\n```elixir\nar: %{\n  enabled: true,\n  lags: 14,\n  regularization: 0.1  # higher = more sparsity\n}\n```\n\nThis is useful when you're not sure how many lags to use. Set a higher `lags` than you think you need and let regularization prevent the model from overfitting to noise in distant lags.\n\n### Events\n\nCaptures the impact of special occasions (holidays, promotions, etc.) that affect your time series. Events are modeled as additive effects that spike on specific dates.\n\n```elixir\nalias Explorer.DataFrame\n\n# Define which events to model and their windows\nmodel = Soothsayer.new(%{\n  events: %{\n    \"black_friday\" =\u003e %{lower_window: -1, upper_window: 1},\n    \"christmas\" =\u003e %{lower_window: -3, upper_window: 0}\n  }\n})\n\n# Create a DataFrame with event dates\nevents_df = DataFrame.new(%{\n  \"event\" =\u003e [\"black_friday\", \"black_friday\", \"christmas\", \"christmas\"],\n  \"ds\" =\u003e [~D[2022-11-25], ~D[2023-11-24], ~D[2022-12-25], ~D[2023-12-25]]\n})\n\n# Fit with events\nfitted_model = Soothsayer.fit(model, df, events: events_df)\n\n# Predict (include future events)\nfuture_events = DataFrame.new(%{\n  \"event\" =\u003e [\"black_friday\", \"christmas\"],\n  \"ds\" =\u003e [~D[2024-11-29], ~D[2024-12-25]]\n})\npredictions = Soothsayer.predict(fitted_model, future_dates, events: future_events)\n```\n\n#### Event Windows\n\nWindows allow events to affect surrounding days, not just the event date itself:\n\n- **`lower_window`**: Days before the event (use negative numbers). `-2` means the effect starts 2 days before.\n- **`upper_window`**: Days after the event. `1` means the effect extends 1 day after.\n\nExample: `%{lower_window: -1, upper_window: 1}` creates effects for the day before, the event day, and the day after (3 separate learned coefficients).\n\n#### Getting Event Effects\n\nAfter training, you can extract the learned impact of each event:\n\n```elixir\neffects = Soothsayer.get_event_effects(fitted_model)\n# =\u003e %{\"black_friday_-1\" =\u003e 12.5, \"black_friday_0\" =\u003e 45.2, \"black_friday_+1\" =\u003e 8.3, ...}\n```\n\nThis shows how much each event (at each window position) adds to the forecast.\n\n### Training Parameters\n\n```elixir\nSoothsayer.new(%{\n  epochs: 100,        # training iterations (default: 100)\n  learning_rate: 0.01 # how fast to learn (default: 0.01)\n})\n```\n\nIf your model is underfitting (predictions are too smooth), try more epochs or a higher learning rate. If it's overfitting (fits training data but not new data), try fewer epochs or more regularization.\n\n## Using EXLA for Faster Training\n\nSoothsayer uses EXLA for training by default, which compiles to XLA for faster execution on CPU/GPU.\n\nMake sure EXLA is configured as your Nx backend in `config/config.exs`:\n\n```elixir\nconfig :nx, default_backend: EXLA.Backend\n```\n\nOr set it at runtime:\n\n```elixir\nNx.global_default_backend(EXLA.Backend)\n```\n\n### GPU Memory Configuration\n\nBy default, XLA pre-allocates 90% of GPU memory at startup for performance. This can cause issues if you're sharing the GPU with other applications (like X windows, other ML processes, or running multiple notebooks).\n\nIf you see errors like `CUDNN_STATUS_INTERNAL_ERROR` or out-of-memory errors when starting, configure EXLA to disable preallocation or limit memory usage in `config/config.exs`:\n\n```elixir\n# Disable preallocation (allocates on-demand)\nconfig :exla, :clients,\n  cuda: [platform: :cuda, preallocate: false]\n\n# Or limit to 50% of GPU memory\nconfig :exla, :clients,\n  cuda: [platform: :cuda, memory_fraction: 0.5]\n```\n\nAlternatively, set environment variables before starting your application:\n\n```bash\nexport XLA_PYTHON_CLIENT_PREALLOCATE=false\n# Or: export XLA_PYTHON_CLIENT_MEM_FRACTION=0.5\n```\n\n| Option | Effect |\n|--------|--------|\n| `preallocate: false` | Allocates memory on-demand instead of upfront |\n| `memory_fraction: 0.5` | Pre-allocates only 50% of GPU memory |\n\n## Full Configuration Example\n\nHere's a model configured for daily sales data with yearly seasonality, short-term momentum, and holiday effects:\n\n```elixir\nmodel = Soothsayer.new(%{\n  trend: %{enabled: true, changepoints: 10},\n  seasonality: %{\n    yearly: %{enabled: true, fourier_terms: 8},\n    weekly: %{enabled: true, fourier_terms: 3}\n  },\n  ar: %{\n    enabled: true,\n    lags: 7,\n    regularization: 0.05\n  },\n  events: %{\n    \"black_friday\" =\u003e %{lower_window: -1, upper_window: 1},\n    \"christmas\" =\u003e %{lower_window: -3, upper_window: 0}\n  },\n  epochs: 150,\n  learning_rate: 0.01\n})\n```\n\n## Features Not Yet Implemented\n\nThe following NeuralProphet features are on the roadmap:\n\n- Lagged Regressors (external variables that affect the forecast)\n- Future Regressors (known future values like holidays)\n- Country Holidays (automatic holiday detection via `:holidefs` library)\n- Multiplicative Events (events that scale with trend)\n- Event Regularization\n- Recurring Events (auto-expand to all years)\n- Uncertainty Estimation\n- Multiplicative Seasonality\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\nThis project uses [Conventional Commits](https://www.conventionalcommits.org/) for automated releases. See the [release documentation](https://github.com/georgeguimaraes/soothsayer/blob/main/.github/RELEASE.md) for details.\n\n## License\n\nCopyright 2024 George Guimarães\n\nSoothsayer is released under the Apache License 2.0. See the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorgeguimaraes%2Fsoothsayer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeorgeguimaraes%2Fsoothsayer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorgeguimaraes%2Fsoothsayer/lists"}