xbe.at

Machine learning / Advanced ML topics

Choosing Machine Learning Models for Small vs. Large Datasets

14 min read, 15 sections

Contents
  1. Dataset Size and Model Selection
  2. Linear Regression for Small Datasets
  3. Logistic Regression for Binary Classification
  4. Decision Trees for Interpretable Models
  5. k-Nearest Neighbors (k-NN) for Small Datasets
  6. Random Forests for Large Datasets
  7. Gradient Boosting Machines (GBM) for Large Datasets
  8. Support Vector Machines (SVM) for Complex Decision Boundaries
  9. Dimensionality Reduction with PCA
  10. Handling Structured Data with Decision Trees
  11. Convolutional Neural Networks (CNNs) for Image Data
  12. Recurrent Neural Networks (RNNs) for Sequential Data
  13. Real-life Example: Sentiment Analysis
  14. Real-life Example: Image Classification
  15. Additional Resources

Dataset Size and Model Selection

When choosing a machine learning model, dataset size plays a crucial role. Smaller datasets often benefit from simpler models, while larger datasets can leverage more complex algorithms. Let's explore this relationship using Python examples.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor

def plot_learning_curve(estimator, X, y, title):
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X, y, cv=5, n_jobs=-1, train_sizes=np.linspace(.1, 1.0, 5))
    
    plt.figure(figsize=(10, 6))
    plt.title(title)
    plt.xlabel("Training examples")
    plt.ylabel("Score")
    
    plt.plot(train_sizes, np.mean(train_scores, axis=1), 'o-', label="Training score")
    plt.plot(train_sizes, np.mean(test_scores, axis=1), 'o-', label="Cross-validation score")
    
    plt.legend(loc="best")
    plt.show()

# Generate synthetic data
X = np.random.rand(1000, 1)
y = 3 * X + np.random.randn(1000, 1) * 0.1

# Plot learning curves
plot_learning_curve(LinearRegression(), X, y, "Learning Curve - Linear Regression")
plot_learning_curve(RandomForestRegressor(), X, y, "Learning Curve - Random Forest")

Linear Regression for Small Datasets

Linear regression is a simple yet effective model for small to medium-sized datasets with linear relationships. It's particularly useful when you have limited data points and want to avoid overfitting.

import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt

# Generate a small dataset
np.random.seed(42)
X = np.random.rand(30, 1) * 10
y = 2 * X + 1 + np.random.randn(30, 1)

# Create and fit the model
model = LinearRegression()
model.fit(X, y)

# Plot the results
plt.scatter(X, y, color='blue', label='Data points')
plt.plot(X, model.predict(X), color='red', label='Linear Regression')
plt.xlabel('X')
plt.ylabel('y')
plt.title('Linear Regression on Small Dataset')
plt.legend()
plt.show()

print(f"Coefficient: {model.coef_[0][0]:.2f}")
print(f"Intercept: {model.intercept_[0]:.2f}")

Logistic Regression for Binary Classification

Logistic regression is an excellent choice for small to medium-sized datasets when dealing with binary classification problems. It's simple, interpretable, and often performs well with limited data.

import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix
import matplotlib.pyplot as plt

# Generate a small dataset for binary classification
np.random.seed(42)
X = np.random.randn(100, 2)
y = (X[:, 0] + X[:, 1] > 0).astype(int)

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and fit the model
model = LogisticRegression()
model.fit(X_train, y_train)

# Make predictions
y_pred = model.predict(X_test)

# Calculate accuracy
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")

# Plot decision boundary
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
                     np.arange(y_min, y_max, 0.1))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X[:, 0], X[:, 1], c=y, alpha=0.8)
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.title("Logistic Regression Decision Boundary")
plt.show()

Decision Trees for Interpretable Models

Decision trees are versatile models that work well for both small and medium-sized datasets. They're particularly useful when interpretability is a priority, as they can be easily visualized and explained.

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# Load the Iris dataset
iris = load_iris()
X, y = iris.data, iris.target

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and fit the model
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train)

# Plot the decision tree
plt.figure(figsize=(20,10))
plot_tree(model, feature_names=iris.feature_names, class_names=iris.target_names, filled=True)
plt.title("Decision Tree for Iris Dataset")
plt.show()

# Print accuracy
print(f"Accuracy: {model.score(X_test, y_test):.2f}")

k-Nearest Neighbors (k-NN) for Small Datasets

k-NN is a simple, non-parametric algorithm that works well for small to medium-sized datasets. It's particularly effective when the decision boundary is irregular and you have a balanced dataset.

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
import numpy as np

# Generate a small moon-shaped dataset
X, y = make_moons(n_samples=200, noise=0.15, random_state=42)

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and fit the model
model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train, y_train)

# Plot decision boundary
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                     np.arange(y_min, y_max, 0.02))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.figure(figsize=(10, 8))
plt.contourf(xx, yy, Z, alpha=0.8, cmap=plt.cm.RdYlBu)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.RdYlBu, edgecolor='black')
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.title("k-NN Classification on Moon Dataset")
plt.show()

# Print accuracy
print(f"Accuracy: {model.score(X_test, y_test):.2f}")

Random Forests for Large Datasets

Random Forests are an ensemble learning method that combines multiple decision trees. They're particularly effective for large datasets and can handle high-dimensional data well.

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
import numpy as np

# Generate a large dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=10, 
                           n_classes=2, random_state=42)

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and fit the model
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# Plot feature importances
importances = model.feature_importances_
indices = np.argsort(importances)[::-1]

plt.figure(figsize=(10, 6))
plt.title("Feature Importances in Random Forest")
plt.bar(range(X.shape[1]), importances[indices])
plt.xticks(range(X.shape[1]), [f"Feature {i}" for i in indices], rotation=90)
plt.tight_layout()
plt.show()

# Print accuracy
print(f"Accuracy: {model.score(X_test, y_test):.2f}")

Gradient Boosting Machines (GBM) for Large Datasets

Gradient Boosting Machines, such as XGBoost or LightGBM, are powerful algorithms for large datasets. They often provide state-of-the-art performance on structured data.

from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split, learning_curve
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
import numpy as np

# Generate a large dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=10, 
                           n_classes=2, random_state=42)

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and fit the model
model = GradientBoostingClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# Plot learning curve
train_sizes, train_scores, test_scores = learning_curve(
    model, X, y, cv=5, n_jobs=-1, train_sizes=np.linspace(.1, 1.0, 5))

plt.figure(figsize=(10, 6))
plt.title("Learning Curve for Gradient Boosting")
plt.xlabel("Training examples")
plt.ylabel("Score")
plt.plot(train_sizes, np.mean(train_scores, axis=1), 'o-', label="Training score")
plt.plot(train_sizes, np.mean(test_scores, axis=1), 'o-', label="Cross-validation score")
plt.legend(loc="best")
plt.show()

# Print accuracy
print(f"Accuracy: {model.score(X_test, y_test):.2f}")

Support Vector Machines (SVM) for Complex Decision Boundaries

SVMs are powerful for both small and large datasets, especially when dealing with complex decision boundaries. They work well in high-dimensional spaces and are effective when the number of dimensions is greater than the number of samples.

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

# Generate a dataset with circular decision boundary
X, y = make_circles(n_samples=1000, noise=0.1, factor=0.2, random_state=42)

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and fit the model
model = SVC(kernel='rbf', random_state=42)
model.fit(X_train, y_train)

# Plot decision boundary
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                     np.arange(y_min, y_max, 0.02))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.figure(figsize=(10, 8))
plt.contourf(xx, yy, Z, alpha=0.8, cmap=plt.cm.RdYlBu)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.RdYlBu, edgecolor='black')
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.title("SVM Classification with RBF Kernel")
plt.show()

# Print accuracy
print(f"Accuracy: {model.score(X_test, y_test):.2f}")

Dimensionality Reduction with PCA

When dealing with high-dimensional data, dimensionality reduction techniques like Principal Component Analysis (PCA) can be crucial. PCA helps to reduce the number of features while retaining most of the variance in the data.

from sklearn.decomposition import PCA
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt

# Load the digits dataset
digits = load_digits()
X, y = digits.data, digits.target

# Apply PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

# Plot the results
plt.figure(figsize=(10, 8))
colors = ['r', 'g', 'b', 'c', 'm', 'y', 'k', 'orange', 'purple', 'brown']
for i, c in zip(range(10), colors):
    plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], c=c, label=str(i))
plt.xlabel("First Principal Component")
plt.ylabel("Second Principal Component")
plt.title("PCA of Digits Dataset")
plt.legend()
plt.show()

# Print explained variance ratio
print(f"Explained variance ratio: {pca.explained_variance_ratio_}")

Handling Structured Data with Decision Trees

Decision trees and their ensemble methods like Random Forests work exceptionally well with structured data. They can capture complex relationships and interactions between features.

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# Load the Iris dataset (an example of structured data)
iris = load_iris()
X, y = iris.data, iris.target

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Create and fit the model
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train)

# Plot the decision tree
plt.figure(figsize=(20,10))
plot_tree(model, feature_names=iris.feature_names, class_names=iris.target_names, filled=True)
plt.title("Decision Tree for Iris Dataset")
plt.show()

# Print feature importances
importances = model.feature_importances_
for f, imp in zip(iris.feature_names, importances):
    print(f"{f}: {imp:.4f}")

# Print accuracy
print(f"Accuracy: {model.score(X_test, y_test):.2f}")

Convolutional Neural Networks (CNNs) for Image Data

When dealing with unstructured image data, Convolutional Neural Networks (CNNs) are the go-to choice. They can automatically learn hierarchical features from raw pixel data.

import tensorflow as tf
from tensorflow.keras import layers, models
import matplotlib.pyplot as plt

# Load and preprocess the MNIST dataset
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255

# Build the CNN model
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(10, activation='softmax')
])

# Compile and train the model
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model.fit(train_images, train_labels, epochs=5, validation_split=0.2)

# Plot training history
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

# Evaluate the model
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print(f"Test accuracy: {test_acc:.4f}")

Recurrent Neural Networks (RNNs) for Sequential Data

When working with sequential or time-series data, Recurrent Neural Networks (RNNs) and their variants like LSTMs are particularly effective. They can capture temporal dependencies in the data.

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models
import matplotlib.pyplot as plt

# Generate synthetic time series data
def generate_time_series(batch_size, n_steps):
    freq1, freq2, offsets1, offsets2 = np.random.rand(4, batch_size, 1)
    time = np.linspace(0, 1, n_steps)
    series = 0.5 * np.sin((time - offsets1) * (freq1 * 10 + 10))
    series += 0.2 * np.sin((time - offsets2) * (freq2 * 20 + 20))
    series += 0.1 * (np.random.rand(batch_size, n_steps) - 0.5)
    return series[..., np.newaxis].astype(np.float32)

# Prepare the data
n_steps = 50
series = generate_time_series(10000, n_steps + 1)
X_train, y_train = series[:7000, :n_steps], series[:7000, -1]
X_valid, y_valid = series[7000:9000, :n_steps], series[7000:9000, -1]
X_test, y_test = series[9000:, :n_steps], series[9000:, -1]

# Build the RNN model
model = models.Sequential([
    layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]),
    layers.SimpleRNN(20),
    layers.Dense(1)
])

# Compile and train the model
model.compile(optimizer='adam', loss='mse')
history = model.fit(X_train, y_train, epochs=20, validation_data=(X_valid, y_valid))

# Plot training history
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.xlabel('Epoch')
plt.ylabel('Mean Squared Error')
plt.legend()
plt.show()

# Evaluate the model
mse = model.evaluate(X_test, y_test)
print(f"Test MSE: {mse:.4f}")

Real-life Example: Sentiment Analysis

Sentiment analysis is a common application of machine learning in natural language processing. It involves determining the emotional tone behind a series of words, often to gain an understanding of the attitudes, opinions and emotions expressed within online mentions.

import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, classification_report

# Sample dataset
texts = [
    "I love this product, it's amazing!",
    "The service was terrible, I'm very disappointed.",
    "This movie is okay, nothing special.",
    "The food was delicious, I highly recommend it!",
    "I hate this app, it's so buggy and slow.",
    "The concert was fantastic, best night ever!",
    "This book is boring, I couldn't finish it.",
    "Great customer support, they solved my issue quickly.",
    "The hotel room was dirty and uncomfortable.",
    "I'm satisfied with my purchase, good value for money."
]
labels = [1, 0, 1, 1, 0, 1, 0, 1, 0, 1]  # 1 for positive, 0 for negative

# Split the data
X_train, X_test, y_train, y_test = train_test_split(texts, labels, test_size=0.2, random_state=42)

# Vectorize the text
vectorizer = CountVectorizer()
X_train_vectorized = vectorizer.fit_transform(X_train)
X_test_vectorized = vectorizer.transform(X_test)

# Train a Naive Bayes classifier
clf = MultinomialNB()
clf.fit(X_train_vectorized, y_train)

# Make predictions
y_pred = clf.predict(X_test_vectorized)

# Print results
print("Accuracy:", accuracy_score(y_test, y_pred))
print("\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=['Negative', 'Positive']))

# Test on a new sentence
new_text = ["This product exceeded my expectations!"]
new_text_vectorized = vectorizer.transform(new_text)
prediction = clf.predict(new_text_vectorized)
print("\nSentiment of '{}': {}".format(new_text[0], 'Positive' if prediction[0] == 1 else 'Negative'))

Real-life Example: Image Classification

Image classification is a fundamental task in computer vision with numerous real-world applications, from facial recognition to medical imaging diagnosis. Here's a simple example using a pre-trained model on the CIFAR-10 dataset.

import tensorflow as tf
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model
import matplotlib.pyplot as plt

# Load and preprocess the CIFAR-10 dataset
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0

# Define the class names
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

# Create the base pre-trained model
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(32, 32, 3))

# Add a global spatial average pooling layer
x = base_model.output
x = GlobalAveragePooling2D()(x)

# Add a fully-connected layer
x = Dense(1024, activation='relu')(x)

# Add a logistic layer with 10 classes
predictions = Dense(10, activation='softmax')(x)

# Construct the full model
model = Model(inputs=base_model.input, outputs=predictions)

# Compile the model
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# Train the model
history = model.fit(x_train, y_train, epochs=10, validation_split=0.2, batch_size=128)

# Evaluate the model
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
print(f"Test accuracy: {test_acc:.4f}")

# Plot training history
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

# Make predictions on a few test images
predictions = model.predict(x_test[:5])
for i in range(5):
    plt.imshow(x_test[i])
    plt.title(f"Predicted: {class_names[predictions[i].argmax()]}, Actual: {class_names[y_test[i][0]]}")
    plt.axis('off')
    plt.show()

Additional Resources

For those interested in diving deeper into machine learning algorithms and their applications, here are some valuable resources:

  1. "Machine Learning" by Tom Mitchell - A comprehensive introduction to machine learning concepts and algorithms.
  2. "Pattern Recognition and Machine Learning" by Christopher Bishop - An in-depth exploration of machine learning techniques.
  3. "Deep Learning" by Ian Goodfellow, Yoshua Bengio, and Aaron Courville - A comprehensive guide to deep learning methods.
  4. ArXiv.org Machine Learning section (https://arxiv.org/list/stat.ML/recent) - For the latest research papers in machine learning.
  5. Coursera's Machine Learning course by Andrew Ng - An excellent online course for beginners.
  6. Fast.ai - Practical deep learning courses for coders.
  7. Kaggle.com - A platform for data science competitions and a wealth of datasets and notebooks.
  8. Scikit-learn documentation (https://scikit-learn.org/stable/documentation.html) - Comprehensive guide to using scikit-learn for machine learning in Python.
  9. TensorFlow tutorials (https://www.tensorflow.org/tutorials) - Official tutorials for deep learning with TensorFlow.

These resources cover a wide range of topics from basic concepts to advanced techniques in machine learning and deep learning.

More in Advanced ML topics

  1. Comparing Machine Learning Techniques Transfer Fine-tuning Multitask Federated11 min

    Transfer learning enables leveraging knowledge from a pre-trained model to solve a new but related task. This technique is particularly effective when...

  2. Causal Learning Discovering New Machine Learning Frontiers17 min

    Causal learning extends beyond traditional correlation-based machine learning by explicitly modeling cause-and-effect relationships between variables. This...

  3. Comparing Multiple Machine Learning Algorithms12 min

    When developing machine learning solutions, it's crucial to explore various algorithms rather than settling on the first one that yields acceptable results....

  4. Causal Inference in Machine Learning in Python6 min

    Causal inference is the process of determining the cause-and-effect relationships between variables in a dataset. It plays a crucial role in many fields...

  5. Computational Graphs for Machine Learning in Python9 min

    Computational graphs are powerful tools for representing and optimizing complex mathematical operations in machine learning. They form the backbone of modern...

  6. Calculus and the Brachistochrone Problem in Machine Learning Using Python7 min

    The Brachistochrone Problem, posed by Johann Bernoulli in 1696, seeks the curve of fastest descent between two points under gravity. This classical problem...