Hoppa till huvudinnehåll

Maskininlärning

Fallstudie 1: Linjär Regression

Detta är ett av de enklaste exemplen på regression. Målet är att dra en rak linje som bäst passar en samling datapunkter, t.ex. för att förutsäga huspriser baserat på boyta.

  • Modellen: En enkel linje, y = mx + c, där m (lutning) och c (skärningspunkt) är modellens "vikter".
  • Kostnadsfunktionen: Man använder Mean Squared Error (MSE), som beräknar det genomsnittliga kvadratiska avståndet från varje datapunkt till linjen. Målet är att hitta den linje som minimerar detta totala avstånd.
  • Lärandet: Modellen använder Gradient Descent för att hitta de optimala värdena på m och c. Den startar med en slumpmässig linje, beräknar felet (MSE), och justerar sedan m och c stegvis i den riktning som minskar felet, tills linjen passar datan så bra som möjligt.
Python-exempel

Med biblioteket scikit-learn kan man träna en linjär regressionsmodell på bara några rader kod:

from sklearn.linear_model import LinearRegression

# Ladda din data (X = boyta, y = pris)
model = LinearRegression()
model.fit(X, y)
# Modellen är nu tränad och kan göra förutsägelser

Fallstudie 2: Beslutsträd i Praktiken

Ett beslutsträd är en kraftfull och lättolkad modell för klassificering. Den lär sig en serie av OM-DÅ-regler som delar upp datan i allt renare grupper. Istället för att bara beskriva det, låt oss bygga ett och visualisera det med scikit-learn på vårt välkända Iris-dataset.

  • Hur det fungerar: Algoritmen försöker hitta den bästa frågan att ställa för att dela upp datan. Vad är en "bra" fråga? Det är en fråga (t.ex. "Är petal length < 2.45 cm?") som resulterar i två grupper som är så "rena" som möjligt, dvs. där varje grupp så långt som möjligt bara innehåller en enda klass. För att mäta detta används ett mått som Gini Impurity. Processen upprepas sedan för varje ny grupp, och trädet växer tills det har klassificerat all data.

Det bästa sättet att förstå ett beslutsträd är att se det. Koden nedan tränar en DecisionTreeClassifier och använder sedan matplotlib för att rita upp exakt de regler som modellen har lärt sig.

# decision_tree_iris.py
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier, plot_tree

# 1. Ladda data
iris = load_iris()
X, y = iris.data, iris.target

# 2. Skapa och träna modellen
# Vi sätter max_depth=3 för att trädet inte ska bli för stort och svårläst
clf = DecisionTreeClassifier(max_depth=3, random_state=42)
clf.fit(X, y)

# 3. Visualisera trädet
plt.figure(figsize=(20,10))
plot_tree(clf,
filled=True,
rounded=True,
class_names=iris.target_names,
feature_names=iris.feature_names)
plt.title("Beslutsträd tränat på Iris-datasetet")
plt.show()

När du kör koden kommer ett diagram att visas. Varje ruta (nod) i trädet representerar en fråga. Genom att följa frågorna från roten (översta noden) ner till ett löv (en nod utan barn) kan du se exakt hur modellen skulle klassificera en ny blomma. Detta är en av de största fördelarna med beslutsträd: till skillnad från ett neuralt nätverk är de inte en "svart låda". Vi kan inspektera och förstå exakt hur de resonerar.

Bortom Enskilda Träd: Ensemble-metoder

Ett enda beslutsträd kan vara instabilt. Om du ändrar en liten detalj i träningsdatan kan hela trädet se annorlunda ut. Lösningen? Bygg en skog! Detta kallas Ensemble Learning – att kombinera många svaga modeller för att skapa en stark.

  1. Random Forest (Slumpmässig Skog): Tänk dig att du tränar 100 beslutsträd. Varje träd får bara se en slumpmässig del av datan och får bara använda en slumpmässig del av frågorna (features). När vi ska klassificera en ny datapunkt får alla 100 träd rösta. Majoriteten vinner. Detta minskar risken för fel drastiskt (Bagging).
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split

# Ladda dataset
data = load_wine()
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.3)

# Träna en slumpmässig skog
clf = RandomForestClassifier(n_estimators=100) # 100 träd
clf.fit(X_train, y_train)

print(f"Noggrannhet: {clf.score(X_test, y_test):.2f}")
  1. Boosting (XGBoost, CatBoost, LightGBM): Här tränar vi inte träden parallellt, utan i serie.
    • Träd 1 gör sina gissningar. Vissa blir fel.
    • Träd 2 tränas specifikt för att rätta till Träd 1:s misstag.
    • Träd 3 tränas för att rätta till Träd 2:s misstag. Detta skapar en extremt skarp modell. XGBoost och CatBoost är idag dominerande i tävlingar på Kaggle när det gäller strukturerad data (tabeller), ofta överlägsna neurala nätverk.

Support Vector Machines (SVM) & The Kernel Trick

Innan djupinlärning tog över var SVM kungen av klassificering. Idén är geometrisk: Hitta den "bredaste gatan" (margin) som separerar två klasser av data.

Men vad om datan inte kan separeras med en rak linje (som i XOR-problemet)? SVM har ett matematiskt ess i rockärmen: The Kernel Trick. Föreställ dig att du har röda och blå punkter på ett papper som inte kan separeras med en linje. Kernel-tricket är som att lyfta upp pappret i 3D och vika det, så att de röda punkterna hamnar på ena sidan av veckat och de blå på andra. Genom att projicera data i högre dimensioner blir omöjliga problem plötsligt lösbara med en enkel "rak linje" (hyperplan) i den nya dimensionen.

import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from sklearn.svm import SVC
import numpy as np

# 1. Skapa "omöjlig" data (cirklar inuti cirklar)
X, y = make_circles(n_samples=100, factor=0.1, noise=0.1)

# 2. Träna en SVM med 'RBF' kernel (Radial Basis Function)
# Detta är "tricket" som lyfter datan till oändliga dimensioner
clf = SVC(kernel='rbf', C=1.0)jo men 2,2,1
clf.fit(X, y)

# 3. Visualisera beslutsgränsen
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='coolwarm')

# Skapa ett rutnät för att rita bakgrundsfärgen
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 30),
np.linspace(ylim[0], ylim[1], 30))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# Rita konturerna (gränsen)
ax.contour(xx, yy, Z, colors='k', levels=[0], alpha=0.5, linestyles=['-'])
plt.title("SVM med Kernel Trick: Cirklar lösta!")
plt.show()

Fallstudie 1: Linjär Regression

Detta är ett av de enklaste exemplen på regression. Målet är att dra en rak linje som bäst passar en samling datapunkter, t.ex. för att förutsäga huspriser baserat på boyta.

  • Modellen: En enkel linje, y = mx + c, där m (lutning) och c (skärningspunkt) är modellens "vikter".
  • Kostnadsfunktionen: Man använder Mean Squared Error (MSE), som beräknar det genomsnittliga kvadratiska avståndet från varje datapunkt till linjen. Målet är att hitta den linje som minimerar detta totala avstånd.
  • Lärandet: Modellen använder Gradient Descent för att hitta de optimala värdena på m och c. Den startar med en slumpmässig linje, beräknar felet (MSE), och justerar sedan m och c stegvis i den riktning som minskar felet, tills linjen passar datan så bra som möjligt.
Python-exempel

Med biblioteket scikit-learn kan man träna en linjär regressionsmodell på bara några rader kod:

from sklearn.linear_model import LinearRegression

# Ladda din data (X = boyta, y = pris)
model = LinearRegression()
model.fit(X, y)
# Modellen är nu tränad och kan göra förutsägelser

Fallstudie 2: Beslutsträd i Praktiken

Ett beslutsträd är en kraftfull och lättolkad modell för klassificering. Den lär sig en serie av OM-DÅ-regler som delar upp datan i allt renare grupper. Istället för att bara beskriva det, låt oss bygga ett och visualisera det med scikit-learn på vårt välkända Iris-dataset.

  • Hur det fungerar: Algoritmen försöker hitta den bästa frågan att ställa för att dela upp datan. Vad är en "bra" fråga? Det är en fråga (t.ex. "Är petal length < 2.45 cm?") som resulterar i två grupper som är så "rena" som möjligt, dvs. där varje grupp så långt som möjligt bara innehåller en enda klass. För att mäta detta används ett mått som Gini Impurity. Processen upprepas sedan för varje ny grupp, och trädet växer tills det har klassificerat all data.

Det bästa sättet att förstå ett beslutsträd är att se det. Koden nedan tränar en DecisionTreeClassifier och använder sedan matplotlib för att rita upp exakt de regler som modellen har lärt sig.

# decision_tree_iris.py
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier, plot_tree

# 1. Ladda data
iris = load_iris()
X, y = iris.data, iris.target

# 2. Skapa och träna modellen
# Vi sätter max_depth=3 för att trädet inte ska bli för stort och svårläst
clf = DecisionTreeClassifier(max_depth=3, random_state=42)
clf.fit(X, y)

# 3. Visualisera trädet
plt.figure(figsize=(20,10))
plot_tree(clf,
filled=True,
rounded=True,
class_names=iris.target_names,
feature_names=iris.feature_names)
plt.title("Beslutsträd tränat på Iris-datasetet")
plt.show()

När du kör koden kommer ett diagram att visas. Varje ruta (nod) i trädet representerar en fråga. Genom att följa frågorna från roten (översta noden) ner till ett löv (en nod utan barn) kan du se exakt hur modellen skulle klassificera en ny blomma. Detta är en av de största fördelarna med beslutsträd: till skillnad från ett neuralt nätverk är de inte en "svart låda". Vi kan inspektera och förstå exakt hur de resonerar.

Bortom Enskilda Träd: Ensemble-metoder

Ett enda beslutsträd kan vara instabilt. Om du ändrar en liten detalj i träningsdatan kan hela trädet se annorlunda ut. Lösningen? Bygg en skog! Detta kallas Ensemble Learning – att kombinera många svaga modeller för att skapa en stark.

  1. Random Forest (Slumpmässig Skog): Tänk dig att du tränar 100 beslutsträd. Varje träd får bara se en slumpmässig del av datan och får bara använda en slumpmässig del av frågorna (features). När vi ska klassificera en ny datapunkt får alla 100 träd rösta. Majoriteten vinner. Detta minskar risken för fel drastiskt (Bagging).
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split

# Ladda dataset
data = load_wine()
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.3)

# Träna en slumpmässig skog
clf = RandomForestClassifier(n_estimators=100) # 100 träd
clf.fit(X_train, y_train)

print(f"Noggrannhet: {clf.score(X_test, y_test):.2f}")
  1. Boosting (XGBoost, CatBoost, LightGBM): Här tränar vi inte träden parallellt, utan i serie.
    • Träd 1 gör sina gissningar. Vissa blir fel.
    • Träd 2 tränas specifikt för att rätta till Träd 1:s misstag.
    • Träd 3 tränas för att rätta till Träd 2:s misstag. Detta skapar en extremt skarp modell. XGBoost och CatBoost är idag dominerande i tävlingar på Kaggle när det gäller strukturerad data (tabeller), ofta överlägsna neurala nätverk.

Support Vector Machines (SVM) & The Kernel Trick

Innan djupinlärning tog över var SVM kungen av klassificering. Idén är geometrisk: Hitta den "bredaste gatan" (margin) som separerar två klasser av data.

Men vad om datan inte kan separeras med en rak linje (som i XOR-problemet)? SVM har ett matematiskt ess i rockärmen: The Kernel Trick. Föreställ dig att du har röda och blå punkter på ett papper som inte kan separeras med en linje. Kernel-tricket är som att lyfta upp pappret i 3D och vika det, så att de röda punkterna hamnar på ena sidan av veckat och de blå på andra. Genom att projicera data i högre dimensioner blir omöjliga problem plötsligt lösbara med en enkel "rak linje" (hyperplan) i den nya dimensionen.

import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from sklearn.svm import SVC
import numpy as np

# 1. Skapa "omöjlig" data (cirklar inuti cirklar)
X, y = make_circles(n_samples=100, factor=0.1, noise=0.1)

# 2. Träna en SVM med 'RBF' kernel (Radial Basis Function)
# Detta är "tricket" som lyfter datan till oändliga dimensioner
clf = SVC(kernel='rbf', C=1.0)jo men 2,2,1
clf.fit(X, y)

# 3. Visualisera beslutsgränsen
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='coolwarm')

# Skapa ett rutnät för att rita bakgrundsfärgen
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 30),
np.linspace(ylim[0], ylim[1], 30))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# Rita konturerna (gränsen)
ax.contour(xx, yy, Z, colors='k', levels=[0], alpha=0.5, linestyles=['-'])
plt.title("SVM med Kernel Trick: Cirklar lösta!")
plt.show()

Att Mäta Framgång: Bortom "Accuracy"

Hur vet vi om vår modell är bra? Det intuitiva måttet är Accuracy (Andel korrekta svar). Men det kan vara livsfarligt missvisande.

Exempel: Cancerdiagnos Antag att du bygger en AI för att hitta en ovanlig cancer som bara 1% av befolkningen har. Din modell är lat och gissar alltid: "Frisk".

  • Accuracy: 99% (Fantastiskt!)
  • Nytta: 0% (Den hittar ingen cancer alls).

För att hantera detta (obalanserad data) använder vi bättre mått:

  • Precision: Av alla fall modellen kallade cancer, hur många var cancer? (Undvik falskt alarm).
  • Recall (Sensitivitet): Av alla som faktiskt hade cancer, hur många hittade modellen? (Missa inga fall).
  • F1-Score: Ett balanserat medelvärde av Precision och Recall.

I cancerexemplet hade vår lata modell haft Recall = 0%, vilket direkt hade avslöjat den som värdelös.

from sklearn.metrics import classification_report, confusion_matrix

# Låt oss se hur vår Random Forest presterade i detalj
y_pred = clf.predict(X_test)

print("Confusion Matrix:")
print(confusion_matrix(y_test, y_pred))

print("\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=data.target_names))

Fallstudie: K-Means Clustering i Praktiken

Detta är den mest kända clustering-algoritmen. Målet är att dela in datan i K antal fördefinierade kluster. Algoritmen fungerar iterativt:

  1. Den startar med K slumpmässiga mittpunkter (centroider).
  2. Den tilldelar varje datapunkt till den närmaste centroiden.
  3. Den räknar om positionen för varje centroid baserat på medelvärdet av alla punkter som nu tillhör den.
  4. Den upprepar steg 2 och 3 tills centroiderna slutar flytta på sig.

Låt oss se detta i praktiken. Koden nedan skapar först slumpmässig "blob"-data (som ser ut som moln av punkter) och använder sedan KMeans från scikit-learn för att hitta de underliggande grupperna.

# kmeans_visualization.py
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans

# 1. Skapa ett syntetiskt dataset
# Vi skapar 300 punkter fördelade runt 4 olika centrum.
X, y_true = make_blobs(n_samples=300, centers=4,
cluster_std=0.70, random_state=0)

# 2. Skapa och träna K-Means modellen
# Vi talar om för modellen att vi letar efter 4 kluster.
kmeans = KMeans(n_clusters=4, random_state=0, n_init=10)
kmeans.fit(X)
y_kmeans = kmeans.predict(X)

# 3. Visualisera resultatet
plt.figure(figsize=(8, 6))
# Rita upp punkterna, färgade efter det kluster de tilldelats av KMeans
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis')

# Rita ut de slutgiltiga centroiderna som modellen hittat
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75, marker='X')
plt.title("K-Means Clustering i Aktion")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()

Resultatet är en tydlig visualisering av oövervakad inlärning. Vi gav aldrig modellen något facit (y_true används inte i träningen), men den lyckades ändå på egen hand identifiera de fyra distinkta grupperna i datan och hitta deras mittpunkter. Detta är kärnan i clustering: att hitta struktur i data utan förkunskap.

Fler Verktyg i Lådan

K-Means är inte ensam. Beroende på datans form behövs olika verktyg:

1. KNN (K-Nearest Neighbors) "Säg mig vilka dina vänner är, så ska jag säga vem du är." KNN är en enkel men kraftfull algoritm som klassificerar en ny datapunkt genom att titta på dess grannar.

from sklearn.neighbors import KNeighborsClassifier
# ... (Ladda data som i tidigare exempel) ...
# K=3 betyder "Titta på de 3 närmaste grannarna och låt dem rösta"
neigh = KNeighborsClassifier(n_neighbors=3)
neigh.fit(X, y)
# Enkelt, men kan bli långsamt med enorma dataset eftersom den måste mäta avstånd till ALLA punkter.

2. Gaussian Mixture Models (GMM) K-Means antar att alla kluster är perfekta, runda cirklar. Men verkligheten är ofta "utdragen". GMM är smartare; den antar att kluster är ovala (Gaussiska fördelningar).

from sklearn.mixture import GaussianMixture

# GMM hittar inte bara mitten, utan också formen (variansen) på klustret
gmm = GaussianMixture(n_components=4)
gmm.fit(X)
labels = gmm.predict(X)
# GMM ger också sannolikheter: "55% chans att du tillhör Kluster A"
probs = gmm.predict_proba(X)

3. Autoencoders Ett neuralt nätverk som lär sig att komprimera data. (Vi kommer att bygga en komplett Autoencoder för bildrestaurering i Kapitel 8, så håll ut!)

Verktygslådan

I nästa kapitel kommer vi också att gå igenom Hantverket – hur man städar data, hanterar saknade värden och väljer rätt hyperparametrar. Men för nu, låt oss titta på hur maskininlärning har förändrat svenska företag.

Övningar

Övning 15: Tolka ett Beslutsträd

Syfte: Att översätta det visuella beslutsträdet från läroboken till en uppsättning läsbara IF/ELSE-regler, för att bevisa dess status som en "white box"-modell.

  1. Kör koden: Kör Python-koden från "Fallstudie 2: Beslutsträd i Praktiken" i textboken för att generera bilden av det tränade Iris-trädet.
  2. Analysera bilden: Titta på den översta noden (roten).
    • Vilken fråga ställer den? (t.ex. petal length (cm) <= 2.45).
    • Om True, vart leder den? Om False, vart leder den?
  3. Skriv ner reglerna: Följ varje möjlig väg från roten ner till ett löv och skriv ner det som en IF/ELSE-sats i pseudokod eller vanlig text.
    • Exempel på en regel:
      IF petal length <= 2.45 THEN
      CLASSIFY AS: setosa
      ELSE
      IF petal width <= 1.75 THEN
      ... (fortsätt följa trädet)
  4. Jämför: Har du nu en komplett uppsättning regler som exakt beskriver hur modellen fattar sina beslut?
Reflektera

Jämför detta med det neurala nätverket. Skulle du kunna göra samma sak där – titta på de inlärda vikterna och bias-värdena och skriva ner en uppsättning enkla, mänskligt läsbara regler? Varför är denna egenskap (tolkningsbarhet) så viktig i vissa tillämpningar, som medicinsk diagnostik eller kreditbedömning?


Övning 16: Konsten att Välja rätt 'K'

Syfte: Att utforska en av de största utmaningarna med K-Means clustering: att i förväg veta hur många kluster (K) man ska leta efter.

  1. Använd K-Means-koden: Ta koden från "Fallstudie: K-Means Clustering i Praktiken" i textboken. Den använder make_blobs för att skapa data med 4 tydliga kluster.
  2. Experimentera med K:
    • Kör koden precis som den är, med n_clusters=4. Resultatet bör se perfekt ut.
    • Ändra nu n_clusters till 2. Kör igen. Hur försöker algoritmen tvinga in datan i bara två grupper?
    • Ändra n_clusters till 8. Kör igen. Vad händer nu? Ser du hur några av de naturliga klustren har blivit godtyckligt uppdelade?
  3. Visualisera: Spara bilderna från varje körning och jämför dem sida vid sida.
Reflektera

Denna övning visar att även om K-Means är kraftfullt, kräver det ofta mänsklig expertis för att välja rätt hyperparametrar. I verkliga dataset (som kunddata) vet man sällan det "rätta" antalet kluster i förväg. Hur skulle du kunna gå tillväga för att hitta ett rimligt K för ett helt okänt dataset? (Detta är ett aktivt forskningsområde, med metoder som "Elbow Method" och "Silhouette Score").


Övning 17: Skogarnas Kamp

Syfte: Att jämföra prestandan mellan ett enkelt Beslutsträd och en Random Forest, och se hur ensemble-metoder kan minska variansen (göra modellen stabilare).

  1. Skapa en fil: forest_battle.py.

  2. Förbered data: Använd make_moons från sklearn.datasets för att skapa ett dataset som är lite svårare än Iris (det är inte linjärt separerbart och har lite brus).

    from sklearn.datasets import make_moons
    from sklearn.model_selection import train_test_split
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.metrics import accuracy_score

    # Skapa data som ser ut som två månar (svårt för raka linjer)
    X, y = make_moons(n_samples=500, noise=0.30, random_state=42)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
  3. Träna modellerna:

    • Träna en DecisionTreeClassifier.
    • Träna en RandomForestClassifier (t.ex. med 100 träd).
  4. Jämför: Beräkna och skriv ut accuracy_score för båda på testdatan.

  5. Analysera: Vilken modell vann? Random Forest bör vara mer robust mot bruset i datan.


Övning 18: Titanic med RandomForest

Syfte: Att tillämpa "Hantverket" (datarensning, hantering av kategorier) på ett klassiskt dataset: Titanic.

  1. Skapa en fil: titanic_survival.py.

  2. Ladda ner daxta: Använd Seaborn för att hämta titanic datat som i uppgift 2.

  3. Använd Pandas:

    import pandas as pd
    from sklearn.model_selection import train_test_split
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.metrics import accuracy_score
    import seaborn as sns

    # 1. Ladda data
    df = sns.load_dataset("titanic")

    # 2. Titta på datan
    print(df.head())
    print(df.isnull().sum()) # Kolla efter saknade värden
  4. Städa data (Hantverket):

    • Välj relevanta kolumner (t.ex. Pclass, Sex, Age, SibSp, Parch, Fare).
    • Hantera NaNs: Fyll i saknade åldrar med medelåldern (df['Age'].fillna(df['Age'].mean(), inplace=True)).
    • Hantera Text: Omvandla 'Sex' till siffror (male=0, female=1) eller använd pd.get_dummies.
  5. Träna och Testa:

    • Dela upp i X (features) och y (survived).
    • Kör train_test_split.
    • Träna en RandomForestClassifier.
    • Utvärdera. Vad påverkade överlevnadschansen mest? (Tips: kolla clf.feature_importances_).

Övning 19: Avslöja Dolda Strukturer med PCA

Syfte: Att använda PCA för att visualisera ett högdimensionellt dataset (handskrivna siffror) och se hur det kan hjälpa (eller stjälpa) en modell. Detta är ett standardverktyg i alla AI-olympiader.

  1. Skapa fil: pca_digits.py.

  2. Ladda och Visualisera:

    import matplotlib.pyplot as plt
    from sklearn.datasets import load_digits
    from sklearn.decomposition import PCA
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score

    # 1. Ladda data (bilder på siffror 0-9, 8x8 pixlar = 64 dimensioner)
    digits = load_digits()
    X, y = digits.data, digits.target

    print(f"Original shape: {X.shape}") # (1797, 64)

    # 2. Använd PCA för att krossa 64 dimensioner till 2
    # Varje bild är 64 pixlar. Vi tvingar PCA att hitta de 2 "viktigaste" mönstren
    # som bäst beskriver skillnaderna. Vi byter ut 64 pixel-värden mot 2 koordinater (x, y).
    pca = PCA(n_components=2)
    X_2d = pca.fit_transform(X)

    # 3. Visualisera
    plt.figure(figsize=(10, 8))
    scatter = plt.scatter(X_2d[:, 0], X_2d[:, 1], c=y, cmap='jet', alpha=0.7)
    plt.colorbar(scatter)
    plt.title("Handskrivna siffror projicerade till 2D med PCA")
    plt.show()

    Analys: Ser du hur siffrorna klumpar ihop sig? Vilka siffror verkar lätta att blanda ihop?

  3. Tävlingsmomentet: PCA som Feature Engineering Kör en Random Forest på originaldatan vs. PCA-datan.

    # Dela upp data
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

    # Modell 1: Original (64 features)
    clf1 = RandomForestClassifier(n_estimators=50)
    clf1.fit(X_train, y_train)
    acc1 = accuracy_score(y_test, clf1.predict(X_test))

    # Modell 2: PCA (använd t.ex. 10 komponenter istället för 2 för att behålla mer info)
    pca_10 = PCA(n_components=10)
    X_train_pca = pca_10.fit_transform(X_train)
    X_test_pca = pca_10.transform(X_test) # OBS: Transformera testdatan med samma PCA!

    clf2 = RandomForestClassifier(n_estimators=50)
    clf2.fit(X_train_pca, y_train)
    acc2 = accuracy_score(y_test, clf2.predict(X_test_pca))

    print(f"Accuracy Original (64 dim): {acc1:.2%}")
    print(f"Accuracy PCA (10 dim): {acc2:.2%}")

    Reflektion: Fick vi bättre eller sämre resultat med PCA? Gick det snabbare? I tävlingar handlar det ofta om att hitta balansen mellan att ta bort brus (bra för PCA) och att tappa information (dåligt för PCA).