Current section
Files
Jump to
Current section
Files
lib/decidex.ex
defmodule Decidex do
@moduledoc """
A decision tree library for small datasets.
"""
@typedoc """
A [feature](https://en.wikipedia.org/wiki/Feature_(machine_learning)) - a parameter of the data.
"""
@type feature :: any
@typedoc """
A value of some `feature`.
"""
@type feature_value :: any
@typedoc """
A predicted or actual outcome for an example feature vector `features`.
"""
@type outcome :: any
@typedoc """
A decision tree.
Represented as a recursive data structure, each node of which can either be an `outcome`,
or a tuple of a `feature` and a map from all possible `feature_value`s to subtrees or `outcome`s.
"""
@type t :: {feature, %{feature_value => t | outcome}} | outcome
@typedoc """
A [feature vector](https://en.wikipedia.org/wiki/Feature_(machine_learning)).
Represented as a map from `feature` to corresponding `feature_value`.
"""
@type features :: %{feature => feature_value}
@typedoc """
A training dataset.
Represented as a list of tuples of `features` (feature vectors) and `outcome`s.
"""
@type training_data :: [{features, outcome}]
@doc """
Predicts the outcome for `features` feature vector using `decision_tree`.
Returns an `outcome`.
"""
@spec predict(decision_tree :: t, features :: features) :: outcome
def predict(decision_tree, features)
def predict({feature, value_to_subtree_or_outcome}, features) do
feature_value = Map.fetch!(features, feature)
subtree_or_outcome = Map.fetch!(value_to_subtree_or_outcome, feature_value)
predict(subtree_or_outcome, features)
end
# base case - reached a leaf, returning the expected `outcome`
def predict(outcome, _features), do: outcome
@doc """
Learns a decision tree from `training_data`.
You can switch learning algorithm using `opts` parameter `:algorithm`.
By default it's set to `Decidex.LearningAlgorithms.ID3`.
Returns the learned decision tree.
"""
@spec learn(training_data, opts :: Keyword.t()) :: t()
def learn(training_data, opts \\ []) do
learning_algorithm_module = Keyword.get(opts, :algorithm, Decidex.LearningAlgorithms.ID3)
learning_algorithm_module.learn(training_data)
end
## Quick-start examples
@doc """
An example decision tree.
This is a slightly modified example from
[these slides](http://www.ke.tu-darmstadt.de/lehre/archiv/ws0809/mldm/dt.pdf).
"""
@spec example :: t()
def example() do
{:weather?,
%{
sunny: {:humidity?, %{normal: :yes, high: :no}},
cloudy: :yes,
rain: {:windy?, %{true: :no, false: :yes}}
}}
end
@doc """
An example training dataset.
This is a slightly modified example from
[these slides](http://www.ke.tu-darmstadt.de/lehre/archiv/ws0809/mldm/dt.pdf).
"""
@spec example_training_data :: training_data
def example_training_data() do
[
{%{weather?: :sunny, humidity?: :high, windy?: false}, :no},
{%{weather?: :sunny, humidity?: :high, windy?: true}, :no},
{%{weather?: :cloudy, humidity?: :high, windy?: false}, :yes},
{%{weather?: :rain, humidity?: :normal, windy?: false}, :yes},
{%{weather?: :cloudy, humidity?: :normal, windy?: true}, :yes},
{%{weather?: :sunny, humidity?: :high, windy?: false}, :no},
{%{weather?: :sunny, humidity?: :normal, windy?: false}, :yes},
{%{weather?: :rain, humidity?: :normal, windy?: false}, :yes},
{%{weather?: :sunny, humidity?: :normal, windy?: true}, :yes},
{%{weather?: :cloudy, humidity?: :high, windy?: true}, :yes},
{%{weather?: :cloudy, humidity?: :normal, windy?: false}, :yes},
{%{weather?: :rain, humidity?: :high, windy?: true}, :no},
{%{weather?: :rain, humidity?: :normal, windy?: true}, :no},
{%{weather?: :rain, humidity?: :high, windy?: false}, :yes}
]
end
end