<jupyter_start><jupyter_text>Converting multiclass vector datasets[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/srlearn/relational-datasets/blob/main/docs/notebooks/02_multiclass.ipynb)[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/srlearn/relational-datasets/HEAD?filepath=docs%2Fnotebooks%2F02_multiclass.ipynb)**Abstract**: This tutorial extends some ideas in the *Converting machine learning benchmark datasets* to demonstrate how multiclass datasets work.Examples in this notebook are provided as documentation, and are available under the terms of the Apache 2.0 License.<jupyter_code>!pip install relational-datasets<jupyter_output><empty_output><jupyter_text>Refresher on Binary ClassificationWhen `y` is a vector containing 0 and 1, then examples are automatically split into positive and negative examples:<jupyter_code>from relational_datasets.convert import from_numpy
import numpy as np

binary_data, binary_modes = from_numpy(
    np.array([[0, 1, 1], [0, 1, 2], [1, 2, 2]]),
    np.array([0, 0, 1]),
)

binary_data.pos
binary_data.neg<jupyter_output><empty_output><jupyter_text>When `y` is a vector containing *more* than 0 and 1, then we're in a multiclass setting.<jupyter_code>multiclass_data, multiclass_modes = from_numpy(
    np.array([[0, 1, 1], [0, 1, 2], [1, 2, 2]]),
    np.array([0, 1, 2]),
)

multiclass_data.pos<jupyter_output><empty_output><jupyter_text>In this case, all of the examples are placed into the *positive examples*, and the *negative examples* are left empty. For classification, data should be further split into $K$ one-versus-rest datasets.<jupyter_code>multiclass_data.neg<jupyter_output><empty_output><jupyter_text>The modes should reflect this difference:<jupyter_code>binary_modes[-1]
multiclass_modes[-1]<jupyter_output><empty_output><jupyter_text>Worked example with scikit-learn's `load_iris`Here we: (**1**) load the data and class labels, (**2**) split into training and test sets, (**3**) bin the continuous features to discrete, and (**4**) convert to the relational format.<jupyter_code>!pip install scikit-learn
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import KBinsDiscretizer<jupyter_output><empty_output><jupyter_text>(1) Load the data, target, and variable namesInvoking `load_iris` returns a dictionary-like object with keys for `.data`, `.target`, `.feature_names`, and `.target_names`. We'll use these to pull out our `X` matrix, `y` array, and variable names.<jupyter_code>iris = load_iris()

X = iris.data
y = iris.target
variable_names = [name.replace("(cm)", "").replace(" ", "") for name in iris.feature_names] + [iris.target_names[1]]

y
variable_names<jupyter_output><empty_output><jupyter_text>(2) Split out training and test sets<jupyter_code>X_train, X_test, y_train, y_test = train_test_split(X, y)<jupyter_output><empty_output><jupyter_text>(3) Discretize continuous features to discretescikit-learn's `KBinsDiscretizer` will help us here, but we'll want an ordinal (0, 1, 2, 3, 4) encoding for our discrete features rather than the default one-hot encoding, and we need to ensure that the resulting matrices are converted back to integers.<jupyter_code>disc = KBinsDiscretizer(n_bins=5, encode="ordinal")

X_train = disc.fit_transform(X_train).astype(int)
X_test = disc.transform(X_test).astype(int)
iris_train, iris_modes = from_numpy(X_train, y_train, names=variable_names)

iris_modes<jupyter_output><empty_output><jupyter_text>(4) Convert arrays to `RelationalDataset`Finally, let's convert our training and test folds into RelationalDatasets and modes:<jupyter_code>iris_test, _ = from_numpy(X_test, y_test, names=variable_names)
len(iris_train.pos), len(iris_train.neg), len(iris_train.facts)
len(iris_test.pos), len(iris_test.neg), len(iris_test.facts)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11533586818757921, 'fraction_numerical': 0.013688212927756654, 'mean_word_length': 7.2899159663865545, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '236759', 'license': 'Apache-2.0', 'n_tokens_mistral': 1382, 'n_tokens_neox': 1308, 'n_words': 344, 'path': 'docs/notebooks/02_multiclass.ipynb', 'repo_name': 'vishalbelsare/relational-datasets', 'size': '3945'}