CSI 4506 - Automne 2025
Version: oct. 5, 2025 12h32
Après avoir complété le devoir 1, vous avez généré un fichier .csv
contenant des données nettoyées.
Pourquoi des étapes supplémentaires seraient nécessaires?
Author: Ronny Kohavi and Barry Becker
Source: UCI - 1996
Please cite: Ron Kohavi, “Scaling Up the Accuracy of Naive-Bayes Classifiers: a Decision-Tree Hybrid”, Proceedings of the Second International Conference on Knowledge Discovery and Data Mining, 1996
Prediction task is to determine whether a person makes over 50K a year. Extraction was done by Barry Becker from the 1994 Census database. A set of reasonably clean records was extracted using the following conditions: ((AAGE>16) && (AGI>100) && (AFNLWGT>1)&& (HRSWK>0))
This is the original version from the UCI repository, with training and test sets merged.
Variables are all self-explanatory except fnlwgt. This is a proxy for the demographic background of the people: “People with similar demographic characteristics should have similar weights”. This similarity-statement is not transferable across the 51 different states.
Description from the donor of the database:
The weights on the CPS files are controlled to independent estimates of the civilian noninstitutional population of the US. These are prepared monthly for us by Population Division here at the Census Bureau. We use 3 sets of controls. These are: 1. A single cell estimate of the population 16+ for each state. 2. Controls for Hispanic Origin by age and sex. 3. Controls by Race, age and sex.
We use all three sets of controls in our weighting program and “rake” through them 6 times so that by the end we come back to all the controls we used. The term estimate refers to population totals derived from CPS by creating “weighted tallies” of any specified socio-economic characteristics of the population. People with similar demographic characteristics should have similar weights. There is one important caveat to remember about this statement. That is that since the CPS sample is actually a collection of 51 state samples, each with its own probability of selection, the statement only applies within state.
Ronny Kohavi and Barry Becker. Data Mining and Visualization, Silicon Graphics.
e-mail: ronnyk ‘@’ live.com for questions.
Downloaded from openml.org.
['Private', 'Local-gov', NaN, 'Self-emp-not-inc', 'Federal-gov', 'State-gov', 'Self-emp-inc', 'Without-pay', 'Never-worked']
Categories (8, object): ['Federal-gov', 'Local-gov', 'Never-worked', 'Private', 'Self-emp-inc', 'Self-emp-not-inc', 'State-gov', 'Without-pay']
['Never-married', 'Married-civ-spouse', 'Widowed', 'Divorced', 'Separated', 'Married-spouse-absent', 'Married-AF-spouse']
Categories (7, object): ['Divorced', 'Married-AF-spouse', 'Married-civ-spouse', 'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed']
Points clés sur la représentation des données
Considérons l’attribut workclass
, qui a 8 valeurs distinctes telles que ‘Federal-gov’, ‘Local-gov’, etc.
w
= 1, 2, 3, 4, 5, 6, 7, ou 8w
= [0,0,0], [0,0,1], [0,1,0], \(\ldots\), ou [1,1,1]w
= [1,0,0,0,0,0,0,0], [0,1,0,0,0,0,0,0], \(\ldots\), ou [0,0,0,0,0,0,0,1]Encodage One-Hot: Cette méthode est à privilégier pour les données catégorielles.
w
= 1, 2, 3, etc., cela implique que ‘Federal-gov’ et ‘Local-gov’ sont similaires, tandis que ‘Federal-gov’ et ‘Without-pay’ ne le sont pas.w
= [0,0,0], [0,0,1], etc., pourrait induire en erreur l’algorithme en suggérant une similarité basée sur des schémas numériques.Encodage One-Hot: Une technique qui convertit les variables catégorielles en une représentation vectorielle binaire, où chaque catégorie est représentée par un vecteur avec un seul ‘1’ et tous les autres éléments à ‘0’.
[0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1.]
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# Chargement de l'ensemble de données 'Heart-Disease' depuis OpenML
data = fetch_openml(name='Heart-Disease', version=1, as_frame=True)
df = data.frame
# Remplacer '?' par NaN et convertir les colonnes en numérique
for col in df.columns:
df[col] = pd.to_numeric(df[col], errors='coerce')
# Supprimer les lignes avec des valeurs manquantes
df.dropna(inplace=True)
# Définir les attributs et la cible
X = df.drop(columns=['target'])
y = df['target']
# Colonnes à encoder avec OneHotEncoder
colonnes_a_encoder = ['sex', 'cp', 'fbs', 'restecg', 'exang', 'slope', 'thal']
# Identifier les colonnes numériques
colonnes_numeriques = X.columns.difference(colonnes_a_encoder)
# Diviser l'ensemble de données en ensembles d'entraînement et de test avant les transformations
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Appliquer OneHotEncoder et StandardScaler à l'aide de ColumnTransformer
column_transformer = ColumnTransformer(
transformers=[
('onehot', OneHotEncoder(), colonnes_a_encoder),
('scaler', StandardScaler(), colonnes_numeriques)
]
)
# Ajuster le transformateur sur les données d'entraînement et transformer les données d'entraînement et de test
X_train_processed = column_transformer.fit_transform(X_train)
X_test_processed = column_transformer.transform(X_test)
# Initialiser et entraîner le modèle de régression logistique
model = LogisticRegression(max_iter=1000)
model = model.fit(X_train_processed, y_train)
# Récupérer les noms des attributs après transformation à l'aide de get_feature_names_out()
feature_names = column_transformer.get_feature_names_out()
# Obtenir les coefficients et les associer aux noms des attributs
coefficients = model.coef_[0]
# Créer un DataFrame avec les noms des attributs et les coefficients
coef_df = pd.DataFrame({
'Attribut': feature_names,
'Coefficient': coefficients
})
# Afficher les coefficients associés à 'cp'
cp_features = coef_df[coef_df['Attribut'].str.contains('_cp')]
print("\nCoefficients associés à 'cp' :")
print(cp_features)
Coefficients associés à 'cp' :
Attribut Coefficient
2 onehot__cp_0.0 -1.013382
3 onehot__cp_1.0 -0.212284
4 onehot__cp_2.0 0.599934
5 onehot__cp_3.0 0.628824
L’encodage ordinal est une technique qui attribue des valeurs numériques aux attributs catégoriels en fonction de leur ordre ou de leur classement intrinsèque.
Pour les attributs avec des valeurs comme ‘Mauvais’, ‘Moyen’, et ‘Bon’, un encodage ordinal aurait du sens.
La discrétisation consiste à regrouper des valeurs ordinales en catégories discrètes.
Exemple : Catégoriser les âges en groupes tels que ‘nourrisson’, ‘enfant’, ‘adolescent’, ‘adulte’, et ‘senior’.
Avantages :
Inconvénients :
import pandas as pd
import numpy as np
from sklearn.preprocessing import FunctionTransformer
bins = [0, 1, 13, 20, 60, np.inf]
labels = ['nourrisson', 'enfant', 'adolescent', 'adulte', 'senior']
transformer = FunctionTransformer(
pd.cut, kw_args={'bins': bins, 'labels': labels, 'retbins': False}
)
X = np.array([0.5, 2, 15, 25, 97])
transformer.fit_transform(X)
['nourrisson', 'enfant', 'adolescent', 'adulte', 'senior']
Categories (5, object): ['nourrisson' < 'enfant' < 'adolescent' < 'adulte' < 'senior']
Mettre à l’échelle les attributs garantit que leurs valeurs se situent dans des plages comparables.
Pourquoi la mise à l’échelle des données est-elle une bonne pratique ?
Nous prétendons prédire le prix d’une maison en utilisant la régression par les k-plus proches voisins (KNN) avec deux attributs :
import numpy as np
import pandas as pd
# Trois exemples (pièces, sqft); prix seulement pour b et c (entraînement)
point_names = ["a", "b", "c"]
X = np.array([
[4, 1500.0], # a (requête)
[8, 1520.0], # b (entraînement)
[4, 1300.0], # c (entraînement)
], dtype=float)
prices = pd.Series([np.nan, 520_000, 390_000], index=point_names, name="price")
df = pd.DataFrame(X, columns=["rooms", "sqft"], index=point_names)
display(df)
display(prices.to_frame())
Remarque. Nous considérerons b et c comme l’ensemble d’entraînement, et a comme la requête dont nous voulons prédire le prix.
rooms | sqft | |
---|---|---|
a | 4.0 | 1500.0 |
b | 8.0 | 1520.0 |
c | 4.0 | 1300.0 |
price | |
---|---|
a | NaN |
b | 520000.0 |
c | 390000.0 |
Lorsqu’un attribut a une échelle beaucoup plus grande (par exemple, la superficie en pieds carrés), elle peut dominer la somme.
a | b | c | |
---|---|---|---|
a | 0.000000 | 20.396078 | 200.000000 |
b | 20.396078 | 0.000000 | 220.036361 |
c | 200.000000 | 220.036361 | 0.000000 |
Pour un flux de travail ML équitable, calculez les paramètres d’échelle sur les données d’entraînement (b, c) uniquement, puis transformez à la fois l’entraînement et la requête :
rooms | sqft | |
---|---|---|
a | -1.0 | 0.818182 |
b | 1.0 | 1.000000 |
c | -1.0 | -1.000000 |
a | b | c | |
---|---|---|---|
a | 0.000000 | 2.008247 | 1.818182 |
b | 2.008247 | 0.000000 | 2.828427 |
c | 1.818182 | 2.828427 | 0.000000 |
Nous allons exécuter un régressseur 1-NN (donc la prédiction est exactement le prix du plus proche voisin) avec et sans mise à l’échelle.
# 2) Avec mise à l'échelle (le pipeline ajuste le scaler uniquement sur les données d'entraînement, puis KNN sur les données mises à l'échelle)
knn_scaled = Pipeline([
("scaler", StandardScaler()),
("knn", KNeighborsRegressor(n_neighbors=1, metric="euclidean"))
])
knn_scaled.fit(X_train, y_train)
pred_scaled = knn_scaled.predict(X_query)[0]
pd.DataFrame(
{
"prédiction (sans mise à l'échelle)": [pred_plain],
"prédiction (avec mise à l'échelle)": [pred_scaled],
"plus proche voisin (sans mise à l'échelle)": [point_names[1] if pred_plain==prices['b'] else point_names[2]],
"plus proche voisin (avec mise à l'échelle)": [point_names[1] if pred_scaled==prices['b'] else point_names[2]],
},
index=["a"]
)
prédiction (sans mise à l'échelle) | prédiction (avec mise à l'échelle) | plus proche voisin (sans mise à l'échelle) | plus proche voisin (avec mise à l'échelle) | |
---|---|---|---|---|
a | 520000.0 | 390000.0 | b | c |
Les algorithmes d’apprentissage fonctionnent de manière optimale lorsque les valeurs des attributs ont des plages similaires, telles que [-1,1] ou [0,1].
Normalisation: \[ \frac{x_i^{(j)} - \min^{(j)}}{\max^{(j)} - \min^{(j)}} \]
La standardisation (également appelée normalisation par score-z) transforme chaque attribut pour qu’elle ait une distribution normale avec une moyenne (\(\mu\)) de 0 et un écart type (\(\sigma\)) de 1.
\[ \frac{x_i^{(j)} - \mu^{(j)}}{\sigma^{(j)}} \]
Remarque : Les valeurs ne sont pas bornées !
Caractéristique | Standardisation | Normalisation |
---|---|---|
Plage de sortie | Non bornée | Typiquement [0, 1] |
Centre | Moyenne à 0 | Non centrée |
Sensibilité aux valeurs aberrantes | Faible | Élevée |
Cas d’utilisation principal | Choix par défaut ; pour les modèles supposant des données centrées sur zéro | Lorsque des entrées bornées sont requises (par exemple, traitement d’image, certains réseaux neuronaux) |
Le flux de travail correct :
StandardScaler
) sur les données d’entraînement (scaler.fit(X_train)
).
scaler.transform(X_train)
) et les données de test (scaler.transform(X_test)
) en utilisant le standardiseur qui a été ajusté sur les données d’entraînement.Les valeurs manquantes font référence à l’absence de données ou de valeurs dans un ensemble de données là où une valeur est attendue.
XGBoost
sklearn.linear_model.LinearRegression
ne peuvent pas traiter les valeurs manquantes.L’imputation des données est le processus consistant à remplacer les valeurs manquantes dans un ensemble de données par des valeurs substituées, généralement en utilisant des méthodes statistiques ou d’apprentissage automatique.
Remplacer les valeurs manquantes par la moyenne ou la médiane de l’attribut.
Inconvénients : Ignore les corrélations entre les attributs et les relations complexes.
Imputation par la mode : Remplacer les valeurs manquantes par la valeur la plus fréquente ; ignore également les corrélations entre les attributs.
Méthode de valeur spéciale : Remplacer les valeurs manquantes par une valeur en dehors de la plage normale (par exemple, utiliser -1 ou 2 pour des données normalisées entre [0,1]).
Méthode basée sur les instances :
Méthodes basées sur des modèles :
Le problème de déséquilibre des classes (class imbalance) survient lorsqu’un grand nombre d’exemples appartient à une classe majoritaire, tandis qu’un nombre relativement faible d’exemples appartient à une ou plusieurs classes minoritaires.
Les modèles ont tendance à favoriser la classe majoritaire, ce qui conduit à de mauvaises performances sur la classe minoritaire.
Utiliser l’apprentissage sensible aux coûts ou ajuster les seuils de décision.
class_weight
de SGDClassifier.Appliquer les solutions uniquement à l’ensemble d’entraînement pour éviter les fuites de données!
L’ingénierie des attributs est le processus de création, transformation et sélection de variables (attributs) à partir de données brutes pour améliorer la performance des modèles d’apprentissage automatique.
import numpy as np
np.random.seed(42)
X = 6 * np.random.rand(100, 1) - 3
y = 0.5 * X ** 2 - X + 2 + np.random.randn(100, 1)
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.figure(figsize=(6,4))
plt.plot(X, y, "b.")
plt.xlabel("$x$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([-3, 3, 0, 10])
plt.grid(True)
plt.show()
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X, y)
X_new = np.array([[-3], [3]])
y_pred = lin_reg.predict(X_new)
plt.figure(figsize=(6,4))
plt.plot(X, y, "b.")
plt.plot(X_new, y_pred, "r-")
plt.xlabel("$x$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([-3, 3, 0, 10])
plt.show()
Un modèle linéaire représente mal ces données.
PolynomialFeatures
Générez une nouvelle matrice d’attributs constituée de toutes les combinaisons polynomiales des attributs avec un degré inférieur ou égal au degré spécifié. Par exemple, si un échantillon d’entrée est bidimensionnel et de la forme \([a, b]\), les attributs polynomials de degré 2 sont \([1, a, b, a^2, ab, b^2]\).
PolynomialFeatures
Étant donné deux attributs \(a\) et \(b\), PolynomialFeatures
avec degree=3
ajouterait \(a^2\), \(a^3\), \(b^2\), \(b^3\), ainsi que \(ab\), \(a^2b\), \(ab^2\) !
Avertissement
PolynomialFeatures(degree=d)
ajoute \(\frac{(D+d)!}{d!D!}\) attributs, où \(D\) est le nombre initial d’attributs.
lin_reg = LinearRegression()
lin_reg = lin_reg.fit(X_poly, y)
X_new = np.linspace(-3, 3, 100).reshape(100, 1)
X_new_poly = poly_features.transform(X_new)
y_new = lin_reg.predict(X_new_poly)
plt.figure(figsize=(5, 3))
plt.plot(X, y, "b.")
plt.plot(X_new, y_new, "r-", linewidth=2, label="Prédictions")
plt.xlabel("$x_1$")
plt.ylabel("$y$", rotation=0)
plt.legend(loc="upper left")
plt.axis([-3, 3, 0, 10])
plt.grid()
plt.show()
LinearRegression
sur PolynomialFeatures
Les données ont été générées selon l’équation suivante, avec l’inclusion de bruit gaussien.
\[ y = 0.5 x^2 - 1.0 x + 2.0 \]
Présenté ci-dessous est le modèle appris.
\[ \hat{y} = 0.56 x^2 + (-1.06) x + 1.78 \]
L’augmentation des données (data augmentation) est une technique utilisée pour accroître la diversité d’un ensemble de données en appliquant diverses transformations aux données existantes.
Machine Learning Engineering par Andriy Burkov (A. Burkov 2020).
Traite de la collecte de données, du stockage, du prétraitement, de l’ingénierie des caractéristiques, du test et du débogage des modèles, du déploiement, de la mise hors service, et de la maintenance.
Par l’auteur de The Hundred-Page Machine Learning Book (Andriy Burkov 2019).
Disponible sous un modèle “lire d’abord, acheter plus tard”.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
num_pipeline = Pipeline([
('imputer', SimpleImputer(strategy="median")),
('attribs_adder', CombinedAttributesAdder()),
('std_scaler', StandardScaler()),
])
training_num_tr = num_pipeline.fit_transform(training_num)
full_pipeline = ColumnTransformer([
("num", num_pipeline, num_attribs),
("cat", OneHotEncoder(), ["sequence"]),
])
training_prepared = full_pipeline.fit_transform(training)
Marcel Turcotte
École de science informatique et de génie électrique (SIGE)
Université d’Ottawa
J’ai présenté à GPT-4o une image du personnage principal de Marcel the Shell With Shoes On et j’ai eu les interactions suivantes.
Marcel: How would you describe the subject of the image, its artistic quality, technique, and rendering style?
GPT-4o: The image depicts a whimsical character that resembles a small shell with one large, expressive eye. It stands on two legs wearing shoes, giving it a cute and almost anthropomorphic appearance. The character has a surreal and quirky look, which lends it a sense of personality and charm.
Artistic Quality:
The image is rendered with a high degree of polish and smoothness, possibly created digitally. The textures, shading, and lighting are soft and subtle, giving the character a smooth and rounded look. The rendering captures a delicate balance between realism (in the textures of the shell and shoes) and cartoon-like abstraction (in the exaggerated eye and small stature).
Technique:
The artist appears to have employed a blend of digital painting and 3D-like modeling techniques, with careful attention to detail in the reflections in the eye and the textures of the shell and shoes. The color palette is muted, using soft tones that evoke a gentle, friendly atmosphere.
Rendering Style:
The rendering style is a mix of minimalist and hyperrealist elements. The minimalism is seen in the simplified forms of the character—particularly the body and legs—while the hyperrealism comes through in the detailing of the eye and the subtle textures. This gives the character a tactile, almost tangible quality while maintaining its fantastical, imaginative essence.
The overall effect of the design is both charming and surreal, combining everyday objects (a shell, shoes) with anthropomorphic and fantastical elements to create a unique, playful character.
Marcel: Create an image based on the following description: The image depicts a whimsical character that resembles a small shell with one large, expressive eye. It stands on two legs wearing shoes, giving it a cute and almost anthropomorphic appearance. The character has a surreal and quirky look, which lends it a sense of personality and charm.
Artistic Quality:
The image is rendered with a high degree of polish and smoothness, possibly created digitally. The textures, shading, and lighting are soft and subtle, giving the character a smooth and rounded look. The rendering captures a delicate balance between realism (in the textures of the shell and shoes) and cartoon-like abstraction (in the exaggerated eye and small stature).
Technique:
The artist appears to have employed a blend of digital painting and 3D-like modeling techniques, with careful attention to detail in the reflections in the eye and the textures of the shell and shoes. The color palette is muted, using soft tones that evoke a gentle, friendly atmosphere.
Rendering Style:
The rendering style is a mix of minimalist and hyperrealist elements. The minimalism is seen in the simplified forms of the character—particularly the body and legs—while the hyperrealism comes through in the detailing of the eye and the subtle textures. This gives the character a tactile, almost tangible quality while maintaining its fantastical, imaginative essence.
The overall effect of the design is both charming and surreal, combining everyday objects (a shell, shoes) with anthropomorphic and fantastical elements to create a unique, playful character.
GTP-4o: Here is the image based on the description you provided. Let me know if you’d like to make any adjustments!