Welcome to the exciting world of machine learning! In this chapter, we'll explore the fundamentals of machine learning, including its different types, key concepts, and the intuition behind how machines learn from data. We'll dive into code examples and provide thorough explanations to help you grasp the concepts effectively. We will cover a few machine learning algorithms as examples to illustrate different concepts. Do not be startled if you don’t understand the math behind them. In Appendix A there’s an overview of the relevant math and intuition, but for now stick to this chapter and the code examples within it.
Here's a list of the machine learning algorithms mentioned in the chapter:
LinearRegression
class from scikit-learn.KMeans
class from scikit-learn.KNeighborsClassifier
class from scikit-learn.MultinomialNB
class from scikit-learn.LogisticRegression
class from scikit-learn.SVC
class from scikit-learn.These algorithms will be used used to demonstrate different aspects of machine learning, such as supervised learning, unsupervised learning, reinforcement learning, classification, and sentiment analysis.
Supervised Learning: In supervised learning, the machine learns from labeled data, where each example in the training dataset is associated with a corresponding output or target. The goal is to learn a mapping function that can predict the output for new, unseen inputs.
Example: Predicting house prices based on features like size, location, and number of bedrooms.
Let's consider a simple example of supervised learning using linear regression:
from sklearn.linear_model import LinearRegression
# Training data
X = [[1000], [1500], [2000], [2500], [3000]] # House sizes (square feet)
y = [200000, 250000, 300000, 350000, 400000] # House prices
# Create and train the model
model = LinearRegression()
model.fit(X, y)
# Make predictions
new_house_size = [[2200]]
predicted_price = model.predict(new_house_size)
print("Predicted house price:", predicted_price)
Output:
Predicted house price: [320000.]
Explanation:
LinearRegression
model and train it using the fit()
method, passing the training data.predict()
method.Intuition: Supervised learning is like learning from a teacher. The model is provided with labeled examples (house sizes and prices) and learns to map the input features (size) to the corresponding output (price). By learning this mapping, the model can make predictions for new, unseen instances.
Unsupervised Learning: Unsupervised learning involves learning from unlabeled data, where the machine tries to discover hidden patterns or structures in the data without any explicit guidance.
Example: Clustering customers based on their purchasing behavior to identify different market segments.
Let's explore an example of unsupervised learning using k-means clustering:
from sklearn.cluster import KMeans
# Customer data
X = [[2, 10], [2, 5], [8, 4], [5, 8], [7, 5], [6, 4], [1, 2], [4, 9]]
# Create and fit the model
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
# Get cluster labels for each customer
labels = kmeans.labels_
print("Cluster labels:", labels)
Output:
Cluster labels: [1 0 2 1 2 2 0 1]
Explanation:
KMeans
model, specifying the desired number of clusters (n_clusters=3
).fit()
method.labels_
attribute of the fitted model.Intuition: Unsupervised learning is like discovering patterns in data without any specific guidance. The model explores the inherent structure of the data and groups similar instances together. This can be useful for identifying customer segments, detecting anomalies, or reducing the dimensionality of the data.
Reinforcement Learning: Reinforcement learning is a type of learning where an agent learns to make decisions by interacting with an environment. The agent receives rewards or penalties based on its actions and learns to maximize the cumulative reward over time.
Example: Training a robot to navigate through a maze by giving it positive rewards for reaching the goal and negative rewards for hitting obstacles.
[
[-1, -1, -1, -1, 0], # Row 0: Penalty cells with one neutral cell at the end
[-1, -1, -1, 0, -1], # Row 1: Penalty cells with one neutral cell
[-1, -1, 0, -1, 100], # Row 2: Penalty cells with the goal (100) at the end
[-1, 0, -1, -1, -1], # Row 3: Penalty cells with one neutral cell
[ 0, -1, -1, -1, -1] # Row 4: One neutral cell with penalty cells
]
Let's consider a simple example of reinforcement learning using Q-learning:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import BoundaryNorm
# Define the environment
environment = [
[-1, -1, -1, -1, 0], # Row 0: Penalty cells with one neutral cell at the end
[-1, -1, -1, 0, -1], # Row 1: Penalty cells with one neutral cell
[-1, -1, 0, -1, 100], # Row 2: Penalty cells with the goal (100) at the end
[-1, 0, -1, -1, -1], # Row 3: Penalty cells with one neutral cell
[0, -1, -1, -1, -1] # Row 4: One neutral cell with penalty cells
]
# Define the Q-learning parameters
num_episodes = 1000
learning_rate = 0.5
discount_factor = 0.9
epsilon = 0.1
# Initialize the Q-table
num_states = len(environment)
num_actions = 4
Q = np.zeros((num_states, num_states, num_actions))
# Define the reward function
def get_reward(state):
return environment[state[0]][state[1]]
# Define the action mapping
actions = {
0: (-1, 0), # Up
1: (0, 1), # Right
2: (1, 0), # Down
3: (0, -1) # Left
}
# Q-learning algorithm
for episode in range(num_episodes):
state = (0, 0) # Start from the top-left corner
while True:
# Choose action (epsilon-greedy strategy)
if np.random.uniform(0, 1) < epsilon:
action = np.random.choice(num_actions)
else:
action = np.argmax(Q[state[0], state[1]])
next_state = tuple(np.array(state) + np.array(actions[action]))
# Check if the next state is valid
if (0 <= next_state[0] < num_states) and (0 <= next_state[1] < len(environment[0])):
reward = get_reward(next_state)
Q[state[0], state[1], action] += learning_rate * (reward + discount_factor * np.max(Q[next_state[0], next_state[1]]) - Q[state[0], state[1], action])
state = next_state
# Check if the goal state is reached
if reward == 100:
break
else:
# If the next state is invalid, choose another action
Q[state[0], state[1], action] -= learning_rate # Penalize for invalid move
# Print the optimal path
state = (0, 0)
path = [state]
while get_reward(state) != 100:
action = np.argmax(Q[state[0], state[1]])
next_state = tuple(np.array(state) + np.array(actions[action]))
if (0 <= next_state[0] < num_states) and (0 <= next_state[1] < len(environment[0])):
state = next_state
path.append(state)
else:
break
print("Optimal path:", path)
# Visualize the path with arrows
fig, ax = plt.subplots()
cmap = plt.get_cmap('coolwarm')
bounds = [-1.5, -0.5, 0.5, 100.5]
norm = BoundaryNorm(bounds, cmap.N)
img = ax.imshow(environment, cmap=cmap, norm=norm)
# Draw arrows on the path
for i in range(len(path) - 1):
start = path[i]
end = path[i + 1]
dx = end[1] - start[1]
dy = end[0] - start[0]
ax.arrow(start[1], start[0], dx, dy, head_width=0.2, head_length=0.2, fc='black', ec='black')
# Mark the start and goal
ax.text(0, 0, 'Start', ha='center', va='center', color='white', fontsize=12, fontweight='bold')
ax.text(4, 2, 'Goal', ha='center', va='center', color='white', fontsize=12, fontweight='bold')
# Set grid and labels
ax.set_xticks(np.arange(len(environment[0])))
ax.set_yticks(np.arange(len(environment)))
ax.set_xticklabels(np.arange(len(environment[0])))
ax.set_yticklabels(np.arange(len(environment)))
ax.grid(color='gray', linestyle='-', linewidth=0.5)
plt.colorbar(img, ticks=[-1, 0, 100], orientation='vertical', label='Reward')
plt.show()
Output:
Optimal path: [(0, 0), (0, 1), (1, 1), (1, 2), (1, 3), (1, 4), (2, 4)]
Optimal path (maximizing reward) learnt by the reinforcement learning algorithm,
Explanation:
get_reward()
to retrieve the reward for a given state.num_episodes
).Intuition: Reinforcement learning is like learning through trial and error. The agent interacts with the environment, receives rewards or penalties based on its actions, and learns to make better decisions over time. By exploring different actions and updating the Q-values, the agent learns to maximize the cumulative reward and find the optimal path to the goal.
Linear algebra is a fundamental mathematical tool used in machine learning. Let's quickly review some key concepts:
Vectors: A vector is an ordered list of numbers. In Python, we can represent vectors using NumPy arrays.
import numpy as np
vector = np.array([1, 2, 3])
print("Vector:", vector)
print("Vector shape:", vector.shape)
Output:
Vector: [1 2 3]
Vector shape: (3,)
Explanation:
np.array()
function and pass the elements as a list.shape
attribute of the vector tells us its dimensions. In this case, it is a 1-dimensional array of length 3.Intuition: Vectors are used to represent quantities with both magnitude and direction. They are fundamental building blocks in linear algebra and are used to represent features, weights, and other quantities in machine learning algorithms.
Matrices: A matrix is a 2-dimensional array of numbers. In Python, we can represent matrices using NumPy arrays.
import numpy as np
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print("Matrix:")
print(matrix)
print("Matrix shape:", matrix.shape)
Output:
Matrix:
[[1 2 3]
[4 5 6]
[7 8 9]]
Matrix shape: (3, 3)
Explanation:
np.array()
function and pass the elements as a list of lists, where each inner list represents a row of the matrix.shape
attribute of the matrix tells us its dimensions. In this case, it is a 3x3 matrix (3 rows and 3 columns).Intuition: Matrices are used to represent data in a tabular form, where each row represents an instance (sample) and each column represents a feature (attribute). Matrices are essential for performing mathematical operations and transformations in machine learning algorithms.
Matrix Operations: Linear algebra provides various operations that can be performed on matrices, such as addition, subtraction, multiplication, and transposition.
import numpy as np
matrix1 = np.array([[1, 2],
[3, 4]])
matrix2 = np.array([[5, 6],
[7, 8]])
# Matrix addition
result = matrix1 + matrix2
print("Matrix addition:")
print(result)
# Matrix multiplication
result = np.dot(matrix1, matrix2)
print("Matrix multiplication:")
print(result)
# Matrix transposition
result = matrix1.T
print("Matrix transposition:")
print(result)
Output:
Matrix addition:
[[ 6 8]
[10 12]]
Matrix multiplication:
[[19 22]
[43 50]]
Matrix transposition:
[[1 3]
[2 4]]
Explanation:
np.dot()
function, which computes the dot product between two matrices.T
attribute, which swaps the rows and columns of a matrix.Intuition: Matrix operations are fundamental in machine learning algorithms. Addition and subtraction are used for updating weights and biases, multiplication is used for transforming data and computing outputs, and transposition is used for reshaping data and performing certain computations efficiently.