Course materials ยท Introduction to Machine Learning

[Week 1] Understanding Machine Learning: Starting to Think with Data ๐Ÿค–

English translation

Hello! Welcome to the first session of Introduction to Machine Learning.

Today, we will explore the big picture of what Machine Learning is and its different types.

Set aside complex equations and code for now, and follow along with a focus on concepts and ideas!

๐Ÿง  Module 1: Machine Learning vs. Traditional Programming

๐Ÿ“š Module 2: Three Types of Machine Learning

1. Supervised Learning (Supervised Learning)

# Import libraries
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split

# Hide unnecessary warnings
import warnings
warnings.filterwarnings(action='ignore')


# Generate the full dataset
X, y = make_blobs(n_samples=200, centers=2, random_state=2, cluster_std=1.5)

# Split the data 7:3 into 'practice problems (train)' and an 'actual exam (test)'
(X_train, X_test,
 y_train, y_test) = train_test_split(X, y, test_size=0.3, random_state=42)

# Visualize the problem (the model can see only the 'practice problems')
plt.figure(figsize=(8, 6))
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='coolwarm', s=60)
plt.title("Training Data Visualization")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()

print(f"์ด ๋ฐ์ดํ„ฐ: {len(X)}๊ฐœ")
print(f"์—ฐ์Šต ๋ฌธ์ œ: {len(X_train)}๊ฐœ")
print(f"์‹ค์ „ ์‹œํ—˜: {len(X_test)}๊ฐœ")
<Figure size 800x600 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
์ด ๋ฐ์ดํ„ฐ: 200๊ฐœ
์—ฐ์Šต ๋ฌธ์ œ: 140๊ฐœ
์‹ค์ „ ์‹œํ—˜: 60๊ฐœ
# A human examines the 'practice problems' and creates a rule.
# "If feature 1 (x-axis) is less than 2.5, assign group 0; if greater, assign group 1!"

# Apply this rule to the 'actual exam' data.
rule_based_pred = (X_test[:, 0] > 2.5).astype(int)

# Visualize the results
plt.figure(figsize=(8, 6))
# Display 'actual exam' samples colored by rule-based predictions
plt.scatter(X_test[:, 0], X_test[:, 1], c=rule_based_pred, cmap='coolwarm', s=60)
plt.axvline(x=2.5, color='green', linestyle='--', label='My Rule (x=2.5)')
plt.title("Rule-based Classification Result")
plt.legend()
plt.show()

# Calculate Accuracy by comparing with the true answers for the 'actual exam'
accuracy = np.mean(rule_based_pred == y_test)
print(f"๊ทœ์น™ ๊ธฐ๋ฐ˜์˜ ์‹ค์ „ ์‹œํ—˜ ์ •ํ™•๋„: {accuracy * 100:.2f}%")
<Figure size 800x600 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
๊ทœ์น™ ๊ธฐ๋ฐ˜์˜ ์‹ค์ „ ์‹œํ—˜ ์ •ํ™•๋„: 51.67%
from sklearn.linear_model import LogisticRegression

# The Machine Learning model trains only on the 'practice problem' data.
model = LogisticRegression()
model.fit(X_train, y_train)

# Visualize and compare with the rule-based approach
plt.figure(figsize=(10, 7))
# Color the 'actual exam' data by their true answers
plt.scatter(X_test[:, 0], X_test[:, 1],
            c=y_test, cmap='coolwarm',
            s=60, alpha=0.7)
plt.axvline(x=2.5, color='green', linestyle='--', label='Rule-based')
ax = plt.gca()
xlim = ax.get_xlim()
w = model.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(xlim[0], xlim[1])
yy = a * xx - (model.intercept_[0]) / w[1]
plt.plot(xx, yy, c='black', label='Machine Learning')
plt.title("Machine Learning vs. Rule-based")
plt.legend()
plt.show()

accuracy = model.score(X_test, y_test)
print(f"๋จธ์‹ ๋Ÿฌ๋‹์˜ ์‹ค์ „ ์‹œํ—˜ ์ •ํ™•๋„: {accuracy * 100:.2f}% (์ฒ˜์Œ ๋ณด๋Š” ๋ฌธ์ œ๋„ ๋” ์ž˜ ํ•ด๊ฒฐํ•จ)")
<Figure size 1000x700 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
๋จธ์‹ ๋Ÿฌ๋‹์˜ ์‹ค์ „ ์‹œํ—˜ ์ •ํ™•๋„: 100.00% (์ฒ˜์Œ ๋ณด๋Š” ๋ฌธ์ œ๋„ ๋” ์ž˜ ํ•ด๊ฒฐํ•จ)

2. Unsupervised Learning (Unsupervised Learning)

from sklearn.cluster import KMeans

# Generate and split the full dataset
X_un, _ = make_blobs(n_samples=300, centers=3,
                     random_state=1, cluster_std=1.8)
X_train_un, X_test_un, _, _ = train_test_split(X_un, np.zeros(300),
                                               test_size=0.3, random_state=42)

# Visualize the problem (show only the 'practice problems')
plt.figure(figsize=(8, 6))
plt.scatter(X_train_un[:, 0], X_train_un[:, 1], c='gray', s=60)
plt.title("Traning Data Visualization")
plt.show()
<Figure size 800x600 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
# A human examines the 'practice problems' and arbitrarily chooses group centers.
manual_centers = np.array([[-10, 0], [-2, 8], [0, 0]])

# Classify the 'actual exam' data using these centers.
distances = np.sqrt(((X_test_un - manual_centers[:, np.newaxis])**2).sum(axis=2))
manual_pred = np.argmin(distances, axis=0)

# Visualize the results
plt.figure(figsize=(8, 6))
plt.scatter(X_test_un[:, 0], X_test_un[:, 1],
            c=manual_pred, cmap='viridis', s=60)
plt.scatter(manual_centers[:, 0], manual_centers[:, 1],
            s=200, c='red', marker='X', label='My Centers')
plt.title("Manual Attempt")
plt.legend()
plt.show()
<Figure size 800x600 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
# Learn group centers from the 'practice problems'
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(X_train_un)

# Use the trained model to predict the group of each 'actual exam' sample
ml_pred = kmeans.predict(X_test_un)

# Visualize and compare with the manual approach
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))

# Left: Manual approach results on the actual exam
ax1.scatter(X_test_un[:, 0], X_test_un[:, 1], c=manual_pred, cmap='viridis', s=60)
ax1.scatter(manual_centers[:, 0], manual_centers[:, 1],
            s=200, c='red', marker='X')
ax1.set_title("Manual Attempt")

# Right: Machine Learning results on the actual exam
ax2.scatter(X_test_un[:, 0], X_test_un[:, 1], c=ml_pred, cmap='viridis', s=60)
ax2.scatter(kmeans.cluster_centers_[:, 0],
            kmeans.cluster_centers_[:, 1],
            s=200, c='red', marker='X')
ax2.set_title("Machine Learning")
plt.show()
print("๋จธ์‹ ๋Ÿฌ๋‹์ด '์—ฐ์Šต ๋ฌธ์ œ'์—์„œ ํ•™์Šตํ•œ ์ •ํ™•ํ•œ ์ค‘์‹ฌ์ ์„ ๊ธฐ์ค€์œผ๋กœ '์‹ค์ „ ์‹œํ—˜' ๋ฌธ์ œ๋“ค๋„ ๋” ์ž˜ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค.")
<Figure size 1600x600 with 2 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
๋จธ์‹ ๋Ÿฌ๋‹์ด '์—ฐ์Šต ๋ฌธ์ œ'์—์„œ ํ•™์Šตํ•œ ์ •ํ™•ํ•œ ์ค‘์‹ฌ์ ์„ ๊ธฐ์ค€์œผ๋กœ '์‹ค์ „ ์‹œํ—˜' ๋ฌธ์ œ๋“ค๋„ ๋” ์ž˜ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค.

3. Reinforcement Learning

# Visualize the agent's 'training environment' (the same as supervised learning's train data)
plt.figure(figsize=(8, 6))
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train,
            cmap='coolwarm', s=60, alpha=0.5)
plt.title("Training Data Visualization")
plt.show()
print("์—์ด์ „ํŠธ๋Š” ์ด ํ™˜๊ฒฝ ์†์—์„œ ์ˆ˜๋งŽ์€ ์ ๋“ค์„ ๋งŒ๋‚˜๋ฉฐ ๋ณด์ƒ/๋ฒŒ์ ์„ ํ†ตํ•ด ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.")
<Figure size 800x600 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
์—์ด์ „ํŠธ๋Š” ์ด ํ™˜๊ฒฝ ์†์—์„œ ์ˆ˜๋งŽ์€ ์ ๋“ค์„ ๋งŒ๋‚˜๋ฉฐ ๋ณด์ƒ/๋ฒŒ์ ์„ ํ†ตํ•ด ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.
# Implement simple Reinforcement Learning using the Q-learning idea
# 1. Define States: Divide the space into a grid
grid_x = np.linspace(X_train[:, 0].min(), X_train[:, 0].max(), 10)
grid_y = np.linspace(X_train[:, 1].min(), X_train[:, 1].max(), 10)

# 2. Initialize the Q-table: Store the value of each action (0 or 1) in each grid cell (State)
# Initialize all action values to 0
q_table = np.zeros((len(grid_x), len(grid_y), 2)) # (x-grid cell, y-grid cell, action[0,1])

# 3. Training parameters
learning_rate = 0.1
n_episodes = 1000 # Number of training iterations

# 4. Start training
for episode in range(n_episodes):
    # Randomly select one practice sample
    idx = np.random.randint(len(X_train))
    state_pos, true_label = X_train[idx], y_train[idx]

    # Find the grid cell containing the current position
    state_x_idx = np.digitize(state_pos[0], grid_x) - 1
    state_y_idx = np.digitize(state_pos[1], grid_y) - 1

    # Select an action (choose the one with the higher value)
    action = np.argmax(q_table[state_x_idx, state_y_idx])

    # Calculate the reward
    reward = 1 if action == true_label else -1

    # Update the Q-table: Gradually move the selected action's value toward the reward
    # Q(s,a) <- Q(s,a) + lr * (reward - Q(s,a))
    current_q = q_table[state_x_idx, state_y_idx, action]
    new_q = current_q + learning_rate * (reward - current_q)
    q_table[state_x_idx, state_y_idx, action] = new_q

print("๊ฐ•ํ™”ํ•™์Šต ์™„๋ฃŒ! ๊ฐ ๊ณต๊ฐ„ ์˜์—ญ๋ณ„ ์ตœ์  ํ–‰๋™(์ •์ฑ…)์ด Q-ํ…Œ์ด๋ธ”์— ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")

# Visualize the learned Policy
learned_policy = np.argmax(q_table, axis=2)
plt.figure(figsize=(8, 6))
plt.imshow(learned_policy.T, origin='lower',
           extent=[grid_x[0], grid_x[-1], grid_y[0], grid_y[-1]],
           aspect='auto', cmap='coolwarm', alpha=0.7)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='coolwarm', s=20)
plt.title("Tranined Q-table Visualization")
plt.show()
๊ฐ•ํ™”ํ•™์Šต ์™„๋ฃŒ! ๊ฐ ๊ณต๊ฐ„ ์˜์—ญ๋ณ„ ์ตœ์  ํ–‰๋™(์ •์ฑ…)์ด Q-ํ…Œ์ด๋ธ”์— ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
<Figure size 800x600 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
# A 'real situation' occurs: An unseen point appears (select one from the test data)
test_case_pos = X_test[1]
test_case_label = y_test[1]

# Use the learned Q-table (Policy) to choose the optimal action
test_x_idx = np.digitize(test_case_pos[0], grid_x) - 1
test_y_idx = np.digitize(test_case_pos[1], grid_y) - 1
learned_action = np.argmax(q_table[test_x_idx, test_y_idx])

# Visualize the results
fig, ax = plt.subplots(figsize=(8, 6))
# Background showing the learned Policy
ax.imshow(learned_policy.T, origin='lower',
          extent=[grid_x[0], grid_x[-1], grid_y[0], grid_y[-1]],
          aspect='auto', cmap='coolwarm', alpha=0.7)
# Location of the actual test sample
ax.scatter(test_case_pos[0], test_case_pos[1], c='green', s=200, marker='*')
ax.set_title("Reinforcement Learning Result")

if learned_action == test_case_label:
    reward_text, reward_color = "+1 ๐Ÿ˜„", 'blue'
else:
    reward_text, reward_color = "-1 ๐Ÿ˜ฅ", 'red'

ax.text(test_case_pos[0], test_case_pos[1] + 0.5,
        f"Action: Predict {'Blue' if learned_action==0 else 'Red'}"
        +f"\nResult: {reward_text}",
        ha='center', fontsize=15, color=reward_color)
plt.show()

print("์ˆ˜๋งŽ์€ ๋ณด์ƒ/๋ฒŒ์  ๊ฒฝํ—˜์œผ๋กœ ํ•™์Šต๋œ ์ •์ฑ…์€,")
print(f"์ฒ˜์Œ ๋ณด๋Š” ์ƒํ™ฉ์—์„œ๋„ ๋ณด์ƒ์„ ๋ฐ›์„ ํ™•๋ฅ ์ด ๊ฐ€์žฅ ๋†’์€ ์ตœ์ ์˜ ํ–‰๋™์„ ํ•ฉ๋‹ˆ๋‹ค.")
<Figure size 800x600 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
์ˆ˜๋งŽ์€ ๋ณด์ƒ/๋ฒŒ์  ๊ฒฝํ—˜์œผ๋กœ ํ•™์Šต๋œ ์ •์ฑ…์€,
์ฒ˜์Œ ๋ณด๋Š” ์ƒํ™ฉ์—์„œ๋„ ๋ณด์ƒ์„ ๋ฐ›์„ ํ™•๋ฅ ์ด ๊ฐ€์žฅ ๋†’์€ ์ตœ์ ์˜ ํ–‰๋™์„ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ฆ Module 2.5: What Is a 'Model', the Core of Machine Learning?

While exploring supervised, unsupervised, and reinforcement learning, we have repeatedly used the words 'model' and 'agent'.

The model is the most important concept in Machine Learning.

From now on, using what is called 'Linear Regression' (Linear Regression),

We will learn what the world's simplest 'model box' looks like and how it learns.

# Represent a 'model' as a simple Python 'function'.
# This model takes 'study hours' as input and predicts 'whether the student passes the exam'.

def simple_pass_fail_model(study_hours):
  """
  ์ด ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ํ•˜๋‚˜์˜ ๊ฐ„๋‹จํ•œ '๋ชจ๋ธ'์ž…๋‹ˆ๋‹ค.
  ๋‚ด๋ถ€์—๋Š” '4์‹œ๊ฐ„ ์ด์ƒ ๊ณต๋ถ€ํ•˜๋ฉด ํ†ต๊ณผ'๋ผ๋Š” ๊ทœ์น™(ํŒ๋‹จ ๊ธฐ์ค€)์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  """
  # The model's decision criterion (Rule)
  if study_hours > 4:
    return "Pass"
  else:
    return "Fail"

# Example model use (Inference)
new_student_A_hours = 7
new_student_B_hours = 3

prediction_A = simple_pass_fail_model(new_student_A_hours)
prediction_B = simple_pass_fail_model(new_student_B_hours)

print(f"ํ•™์ƒ A (๊ณต๋ถ€ ์‹œ๊ฐ„: {new_student_A_hours}์‹œ๊ฐ„) -> ์˜ˆ์ธก ๊ฒฐ๊ณผ: {prediction_A}")
print(f"ํ•™์ƒ B (๊ณต๋ถ€ ์‹œ๊ฐ„: {new_student_B_hours}์‹œ๊ฐ„) -> ์˜ˆ์ธก ๊ฒฐ๊ณผ: {prediction_B}")
ํ•™์ƒ A (๊ณต๋ถ€ ์‹œ๊ฐ„: 7์‹œ๊ฐ„) -> ์˜ˆ์ธก ๊ฒฐ๊ณผ: Pass
ํ•™์ƒ B (๊ณต๋ถ€ ์‹œ๊ฐ„: 3์‹œ๊ฐ„) -> ์˜ˆ์ธก ๊ฒฐ๊ณผ: Fail

๐Ÿ“ˆ Module 3: My First Machine Learning Model, "Linear Regression"

Why a 'Linear' Model?

'Linear' has the same meaning as the 1st-degree function y=ax+by = ax + b learned in middle school.

(In Machine Learning, only the variable names change.)

# Generate and split exam-score data based on study hours
study_hours = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
exam_scores = np.array([15, 35, 45, 50, 65, 70, 85, 90, 92, 98])
(X_train_reg, X_test_reg,
 y_train_reg, y_test_reg) = train_test_split(study_hours,
                                             exam_scores,
                                             test_size=0.3,
                                             random_state=42)

# Define 3 candidate models
W1, b1 = 5, 20  # A poor model
W2, b2 = 12, -5 # A mediocre model
W3, b3 = 9.5, 8 # A good model

# Calculate each model's Cost on the 'practice problem' data
pred1_train = W1 * X_train_reg + b1
pred2_train = W2 * X_train_reg + b2
pred3_train = W3 * X_train_reg + b3
cost1_train = np.mean((pred1_train - y_train_reg)**2)
cost2_train = np.mean((pred2_train - y_train_reg)**2)
cost3_train = np.mean((pred3_train - y_train_reg)**2)

# Visualize the 'practice problems'
plt.figure(figsize=(10, 7))
plt.scatter(X_train_reg, y_train_reg, label='Train Data', s=100)
plt.plot(study_hours, W1 * study_hours + b1,
         'r--', label=f'Model 1 (Train Cost: {cost1_train:.2f})')
plt.plot(study_hours, W2 * study_hours + b2,
         'g:', label=f'Model 2 (Train Cost: {cost2_train:.2f})')
plt.plot(study_hours, W3 * study_hours + b3,
         'b-', label=f'Model 3 (Train Cost: {cost3_train:.2f})')
plt.title("Finding a good model")
plt.xlabel("Study Hours")
plt.ylabel("Exam Scores")
plt.legend()
plt.show()
print("์—ฐ์Šต ๋ฌธ์ œ์—์„œ๋Š” ๋ชจ๋ธ 3์˜ Cost๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ์œผ๋ฏ€๋กœ, ๋ชจ๋ธ 3์„ ์ตœ์ข… ๋ชจ๋ธ๋กœ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.")
<Figure size 1000x700 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
์—ฐ์Šต ๋ฌธ์ œ์—์„œ๋Š” ๋ชจ๋ธ 3์˜ Cost๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ์œผ๋ฏ€๋กœ, ๋ชจ๋ธ 3์„ ์ตœ์ข… ๋ชจ๋ธ๋กœ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
# Calculate each model's Cost on the 'actual exam' data
pred1_test = W1 * X_test_reg + b1
pred2_test = W2 * X_test_reg + b2
pred3_test = W3 * X_test_reg + b3
cost1_test = np.mean((pred1_test - y_test_reg)**2)
cost2_test = np.mean((pred2_test - y_test_reg)**2)
cost3_test = np.mean((pred3_test - y_test_reg)**2)

# Visualize the 'actual exam'
plt.figure(figsize=(10, 7))
# Show the 'practice problems' faintly in the background
plt.scatter(X_train_reg, y_train_reg,
            color='gray', alpha=0.3, label='Train Data')
# Show the 'actual exam' data prominently
plt.scatter(X_test_reg, y_test_reg,
            color='blue', label='Test Data', s=100, zorder=5)

# Compare the same 3 candidate lines with the 'actual exam' data
plt.plot(study_hours, W1 * study_hours + b1,
         'r--', label=f'Model 1 (Test Cost: {cost1_test:.2f})')
plt.plot(study_hours, W2 * study_hours + b2,
         'g:', label=f'Model 2 (Test Cost: {cost2_test:.2f})')
plt.plot(study_hours, W3 * study_hours + b3,
         'b-', label=f'Model 3 (Test Cost: {cost3_test:.2f})')
plt.title("Testing a model")
plt.xlabel("Study Hours")
plt.ylabel("Exam Scores")
plt.legend()
plt.show()

print("โœจ ๊ฒฐ๊ณผ: ์—ฐ์Šต ๋ฌธ์ œ์—์„œ ๊ฐ€์žฅ ์ข‹์•˜๋˜ ๋ชจ๋ธ 3์ด,")
print(f"์ฒ˜์Œ ๋ณด๋Š” ์‹ค์ „ ์‹œํ—˜์—์„œ๋„ ๊ฐ€์žฅ ๋‚ฎ์€ Cost๋ฅผ ๊ธฐ๋กํ–ˆ์Šต๋‹ˆ๋‹ค!")
print("\n๋ชจ๋ธ์ด ๋ฐ์ดํ„ฐ๋ฅผ '์•”๊ธฐ'ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ด€๊ณ„๋ฅผ 'ํ•™์Šต(์ผ๋ฐ˜ํ™”)'ํ–ˆ๋‹ค๋Š” ์ฆ๊ฑฐ์ž…๋‹ˆ๋‹ค.")
<Figure size 1000x700 with 1 Axes>
์‹คํ–‰ ๊ฒฐ๊ณผ
โœจ ๊ฒฐ๊ณผ: ์—ฐ์Šต ๋ฌธ์ œ์—์„œ ๊ฐ€์žฅ ์ข‹์•˜๋˜ ๋ชจ๋ธ 3์ด,
์ฒ˜์Œ ๋ณด๋Š” ์‹ค์ „ ์‹œํ—˜์—์„œ๋„ ๊ฐ€์žฅ ๋‚ฎ์€ Cost๋ฅผ ๊ธฐ๋กํ–ˆ์Šต๋‹ˆ๋‹ค!

๋ชจ๋ธ์ด ๋ฐ์ดํ„ฐ๋ฅผ '์•”๊ธฐ'ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ด€๊ณ„๋ฅผ 'ํ•™์Šต(์ผ๋ฐ˜ํ™”)'ํ–ˆ๋‹ค๋Š” ์ฆ๊ฑฐ์ž…๋‹ˆ๋‹ค.