Created
October 8, 2025 20:10
-
-
Save aydinnyunus/cd3c01b932180a1b5cc61c493479ad44 to your computer and use it in GitHub Desktop.
CNN MNIST
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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