Skip to content

Instantly share code, notes, and snippets.

@aydinnyunus
Created October 8, 2025 20:10
Show Gist options
  • Select an option

  • Save aydinnyunus/cd3c01b932180a1b5cc61c493479ad44 to your computer and use it in GitHub Desktop.

Select an option

Save aydinnyunus/cd3c01b932180a1b5cc61c493479ad44 to your computer and use it in GitHub Desktop.
CNN MNIST
# Kullanım:
# python cnn_main.py dosya.png
#
# NOT:
# - İlk çalıştırmada MNIST veri seti indirilecek ve CNN modeli eğitilecek.
# - Bu yüzden internet bağlantısı gereklidir.
# - Gerekli kütüphaneler:
# python -m venv venv
# source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
# pip install numpy pillow scikit-learn matplotlib pandas tensorflow keras
# Dataset: https://www.tensorflow.org/datasets/catalog/mnist
import sys
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, accuracy_score
from PIL import Image, ImageEnhance, ImageOps
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, BatchNormalization
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
def load_mnist_data():
"""Load MNIST data using TensorFlow/Keras"""
print("MNIST verisi indiriliyor (ilk seferde internet gerekiyor)...")
# Load MNIST data
(X_train_full, y_train_full), (X_test_full, y_test_full) = keras.datasets.mnist.load_data()
# Combine train and test data for more training samples
X = np.concatenate([X_train_full, X_test_full])
y = np.concatenate([y_train_full, y_test_full])
# Normalize pixel values
X = X.astype('float32') / 255.0
# Reshape to add channel dimension
X = X.reshape(-1, 28, 28, 1)
# One-hot encode labels
y = to_categorical(y, 10)
return X, y
def create_cnn_model():
"""Create and compile CNN model"""
model = Sequential()
# First Conv Block
model.add(Conv2D(filters=64, kernel_size=(3,3), activation="relu", input_shape=(28,28,1)))
model.add(Conv2D(filters=64, kernel_size=(3,3), activation="relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
# Second Conv Block
model.add(Conv2D(filters=128, kernel_size=(3,3), activation="relu"))
model.add(Conv2D(filters=128, kernel_size=(3,3), activation="relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
# Third Conv Block
model.add(Conv2D(filters=256, kernel_size=(3,3), activation="relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
# Dense layers
model.add(Flatten())
model.add(Dense(512, activation="relu"))
model.add(Dense(10, activation="softmax"))
# Compile model
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
return model
def train_model(model, X_train, y_train, X_val, y_val, epochs=30):
"""Train the CNN model with data augmentation"""
print("Model eğitiliyor...")
# Data augmentation
datagen = ImageDataGenerator(
featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=15,
zoom_range=0.01,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=False,
vertical_flip=False
)
# Callbacks
early_stopping = EarlyStopping(
monitor="val_accuracy",
patience=10,
verbose=1,
mode="max",
restore_best_weights=True
)
reduce_lr = ReduceLROnPlateau(
monitor="val_accuracy",
factor=0.2,
patience=3,
verbose=1,
mode="max",
min_lr=0.00001
)
# Training parameters
batch_size = 128
train_steps = X_train.shape[0] // batch_size
valid_steps = X_val.shape[0] // batch_size
# Create data generators
train_gen = datagen.flow(X_train, y_train, batch_size=batch_size)
val_gen = datagen.flow(X_val, y_val, batch_size=batch_size)
# Train model
history = model.fit(
train_gen,
epochs=epochs,
steps_per_epoch=train_steps,
validation_data=val_gen,
validation_steps=valid_steps,
callbacks=[early_stopping, reduce_lr],
verbose=1
)
return history
def predict_handwritten_image(image_path, model, show=False):
"""Predict digit from handwritten image using CNN model"""
# Load and preprocess image
img = Image.open(image_path).convert('L')
img = img.resize((28, 28))
img = ImageOps.autocontrast(img)
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
# Convert to array and normalize
img_array = np.array(img) / 255.0
# Reshape for CNN input (add batch and channel dimensions)
img_array = img_array.reshape(1, 28, 28, 1)
if show:
plt.figure(figsize=(6, 6))
plt.imshow(img_array.reshape(28, 28), cmap='gray')
plt.title(f"Input Image: {image_path}")
plt.axis('off')
plt.show()
# Make prediction
prediction = model.predict(img_array, verbose=0)
predicted_digit = np.argmax(prediction)
confidence = np.max(prediction) * 100
return predicted_digit, confidence
def plot_training_history(history):
"""Plot training and validation curves"""
fig, ax = plt.subplots(2, 1, figsize=(12, 8))
# Plot loss
ax[0].plot(history.history['loss'], color='b', label="Training loss")
ax[0].plot(history.history['val_loss'], color='r', label="Validation loss")
ax[0].legend(loc='best', shadow=True)
ax[0].set_title('Model Loss')
ax[0].set_xlabel('Epoch')
ax[0].set_ylabel('Loss')
# Plot accuracy
ax[1].plot(history.history['accuracy'], color='b', label="Training accuracy")
ax[1].plot(history.history['val_accuracy'], color='r', label="Validation accuracy")
ax[1].legend(loc='best', shadow=True)
ax[1].set_title('Model Accuracy')
ax[1].set_xlabel('Epoch')
ax[1].set_ylabel('Accuracy')
plt.tight_layout()
plt.show()
def plot_confusion_matrix(model, X_val, y_val):
"""Plot confusion matrix for validation set"""
# Make predictions
y_pred = model.predict(X_val, verbose=0)
y_pred_classes = np.argmax(y_pred, axis=1)
y_true_classes = np.argmax(y_val, axis=1)
# Calculate accuracy
accuracy = accuracy_score(y_true_classes, y_pred_classes) * 100
print(f"Validation setindeki doğruluk oranı: %{accuracy:.2f}")
# Create confusion matrix
cm = confusion_matrix(y_true_classes, y_pred_classes)
# Plot confusion matrix
plt.figure(figsize=(10, 8))
sns.heatmap(cm.T, square=True, annot=True, cbar=False, cmap=plt.cm.Blues, fmt='.0f')
plt.xlabel('Gerçek Değerler')
plt.ylabel('Tahmin Edilen Değerler')
plt.title('Confusion Matrix')
plt.show()
return accuracy
def main():
if len(sys.argv) != 2:
print("Kullanım: python cnn_main.py dosya.png")
sys.exit(1)
image_path = sys.argv[1]
model_path = "mnist_cnn_model.h5"
# Check if image file exists
if not os.path.exists(image_path):
print(f"Hata: {image_path} dosyası bulunamadı!")
sys.exit(1)
# Check if saved model exists
if os.path.exists(model_path):
print(f"Kaydedilmiş model bulundu: {model_path}")
print("Model yükleniyor...")
model = keras.models.load_model(model_path)
print("Model başarıyla yüklendi!")
# Load validation data for evaluation
print("Validation verisi yükleniyor...")
X, y = load_mnist_data()
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.1, random_state=42)
# Evaluate model
print("\nModel değerlendiriliyor...")
accuracy = plot_confusion_matrix(model, X_val, y_val)
print(f"Validation setindeki doğruluk oranı: %{accuracy:.2f}")
else:
print("Kaydedilmiş model bulunamadı. Yeni model eğitiliyor...")
# Load data
X, y = load_mnist_data()
# Split data
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.1, random_state=42)
print(f"Eğitim verisi boyutu: {X_train.shape}")
print(f"Validasyon verisi boyutu: {X_val.shape}")
# Create and train model
model = create_cnn_model()
print("\nModel yapısı:")
model.summary()
# Train model (reduced epochs for faster testing)
history = train_model(model, X_train, y_train, X_val, y_val, epochs=5)
# Evaluate model
print("\nModel değerlendiriliyor...")
accuracy = plot_confusion_matrix(model, X_val, y_val)
# Plot training history
plot_training_history(history)
# Save model
model.save(model_path)
print(f"\nModel '{model_path}' olarak kaydedildi.")
# Predict user's image
print(f"\n{image_path} dosyası tahmin ediliyor...")
pred_digit, confidence = predict_handwritten_image(image_path, model, show=True)
print(f"{image_path} için tahmin edilen rakam: {pred_digit}")
print(f"Güven oranı: %{confidence:.2f}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment