CoolFace
Modelpublic

Alfakurt46/Multimodality_Breast_Cancer_Detection_Project

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
Model Card

-- coding: utf-8 --

"""Çok Modaliteli Meme Kanseri Tespiti Projesi.ipynb

Automatically generated by Colab.

Original file is located at https://colab.research.google.com/drive/1iRYBNFcFPCbFxvIgtkKobOufHoSUvInz """

GPU bellek kullanımını sınırlandır

import tensorflow as tf gpus = tf.config.experimental.listphysicaldevices('GPU') if gpus: try: for gpu in gpus: tf.config.experimental.setmemorygrowth(gpu, True) except RuntimeError as e: print(e)

=============================================================================

0. Gerekli Kütüphaneler ve Ayarlar

=============================================================================

=============================================================================

0. Gerekli Kütüphaneler ve Ayarlar

=============================================================================

import os import zipfile import cv2 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import tensorflow as tf from sklearn.modelselection import StratifiedKFold from sklearn.metrics import accuracyscore, precisionscore, recallscore, f1score, roccurve, auc, confusion_matrix from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.models import Model, Sequential from tensorflow.keras.layers import Input, Dense, Dropout, BatchNormalization, GlobalAveragePooling2D, concatenate, Reshape, Add, LayerNormalization from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau from tensorflow.keras.optimizers import Adam !pip install gradio import gradio as gr import zipfile

=============================================================================

1. Google Drive'ı Mount Et ve Veri Dizini Tanımla

=============================================================================

from google.colab import drive drive.mount('/content/gdrive', force_remount=True)

Veri dizin yapınız:

/content/breast/breast/

├── mamogram/

│ ├── benign/

│ └── malignant/

├── ultrasound/

│ ├── benign/

│ ├── malignant/

│ └── normal/ (bu klasördeki görüntüler benign kabul edilecek)

└── histopathology/

├── benign/ (örn: Adenosis, Fibroadenoma, Tubular Adenoma, Phyllodes Tumor)

└── malignant/ (örn: Ductal Carcinoma, Lobular Carcinoma, Mucinous Carcinoma, Papillary Carcinoma)

BASEDIR = "/content/breast/breast/breast/breast" MAMOGRAMDIR = os.path.join(BASEDIR, "mamogram") ULTRASOUNDDIR = os.path.join(BASEDIR, "ultrasound") HISTOPATHDIR = os.path.join(BASE_DIR, "histopathology")

Ultrasound klasöründe "normal" varsa, içeriğini benign altına taşıyalım.

normaldir = os.path.join(ULTRASOUNDDIR, "normal") benignultrasounddir = os.path.join(ULTRASOUNDDIR, "benign") if os.path.exists(normaldir): os.makedirs(benignultrasounddir, existok=True) for root, dirs, files in os.walk(normaldir): for file in files: if file.lower().endswith(('.png','.jpg','.jpeg','.bmp')): src = os.path.join(root, file) dest = os.path.join(benignultrasounddir, file) os.rename(src, dest) os.rmdir(normal_dir) print("Ultrasound 'normal' klasöründeki görüntüler 'benign' altına taşındı.") else: print("Ultrasound 'normal' klasörü bulunamadı veya zaten taşınmış.")

=============================================================================

2. (Varsa) Zip Dosyasından Verileri Çıkartma

=============================================================================

zippath = "/content/gdrive/MyDrive/breast.zip" # Zip dosyanızın yolu extractpath = BASEDIR # Zip içeriği bu dizine çıkarılacak if os.path.exists(zippath): with zipfile.ZipFile(zippath, 'r') as zipref: zipref.extractall(extractpath) print("Zip dosyası başarıyla çıkarıldı.") else: print("Zip dosyası bulunamadı; verileriniz zaten çıkarılmış olabilir.")

=============================================================================

3. Görüntü Ön İşleme ve Veri Yükleme Fonksiyonları

=============================================================================

IMG_SIZE ayarı: 128x128

IMGSIZE = (128, 128) imageextensions = ('.png', '.jpg', '.jpeg', '.bmp')

def preprocessimage(imagepath, targetsize, datatype): """Görüntüyü yükler, yeniden boyutlandırır ve modality'ye uygun önişleme uygular.""" img = cv2.imread(imagepath) if img is None: print(f"Hata: {imagepath} yüklenemedi") return None img = cv2.resize(img, targetsize) if datatype == "mamogram": lab = cv2.cvtColor(img, cv2.COLORBGR2LAB) l, a, b = cv2.split(lab) clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8)) cl = clahe.apply(l) updatedlab = cv2.merge((cl, a, b)) img = cv2.cvtColor(updatedlab, cv2.COLORLAB2BGR) elif datatype == "histopath": img = cv2.cvtColor(img, cv2.COLORBGR2RGB) elif datatype == "ultrasound": imggray = cv2.cvtColor(img, cv2.COLORBGR2GRAY) imgeq = cv2.equalizeHist(imggray) img = cv2.cvtColor(imgeq, cv2.COLOR_GRAY2BGR) return img / 255.0

def loaddataandorganize(datadir, targetsize, datatype): """ datadir altındaki görüntüleri, alt klasör isimlerine göre etiketleyip yükler. Ultrasound için "normal" klasöründeki görüntüler benign kabul edilir. """ images, labels, filepaths = [], [], [] print(f"\n[{datatype.upper()}] Dosyaları aranıyor: {datadir}") for root, dirs, files in os.walk(datadir): lowerroot = root.lower() if datatype == "ultrasound": if "benign" in lowerroot or "normal" in lowerroot: label = 0 elif "malignant" in lowerroot: label = 1 else: continue else: if "benign" in lowerroot: label = 0 elif "malignant" in lowerroot: label = 1 else: continue for file in files: if file.lower().endswith(imageextensions): imgpath = os.path.join(root, file) img = preprocessimage(imgpath, targetsize, datatype) if img is not None: images.append(img) labels.append(label) filepaths.append(imgpath) else: print(f"Önişleme başarısız: {imgpath}") print(f"\n[{datatype.upper()}] Toplam {len(images)} görüntü yüklendi.") return np.array(images), np.array(labels), pd.DataFrame({"filepath": file_paths, "label": labels})

mamogramimages, mamogramlabels, mamogramdf = loaddataandorganize(MAMOGRAMDIR, IMGSIZE, "mamogram") ultrasoundimages, ultrasoundlabels, ultrasounddf = loaddataandorganize(ULTRASOUNDDIR, IMGSIZE, "ultrasound") histopathimages, histopathlabels, histopathdf = loaddataandorganize(HISTOPATHDIR, IMGSIZE, "histopath")

if mamogramimages.shape[0] == 0: print("Uyarı: Mamogram veri seti boş!") if ultrasoundimages.shape[0] == 0: print("Uyarı: Ultrasound veri seti boş!") if histopath_images.shape[0] == 0: print("Uyarı: Histopatoloji veri seti boş!")

=============================================================================

4. Veri Artırma (Data Augmentation) ve Görselleştirme

=============================================================================

datagen = ImageDataGenerator( rotationrange=20, widthshiftrange=0.2, heightshiftrange=0.2, shearrange=0.2, zoomrange=0.2, horizontalflip=True, fill_mode='nearest' )

def visualizeaugmentation(dataset, title, numimages=5): augmentedimages = [] if len(dataset) > 0: sampleimage = np.expanddims(dataset[0], 0) for i, batch in enumerate(datagen.flow(sampleimage, batchsize=1)): augmentedimages.append(batch[0]) if i >= numimages - 1: break plt.figure(figsize=(15,3)) for idx, augimg in enumerate(augmentedimages): plt.subplot(1, numimages, idx+1) plt.imshow(aug_img) plt.title(f"{title} aug {idx+1}") plt.axis("off") plt.show() else: print(f"{title} veri seti boş!")

print("Mamogram veri artırma örnekleri:") visualizeaugmentation(mamogramimages, "Mamogram") print("Ultrasound veri artırma örnekleri:") visualizeaugmentation(ultrasoundimages, "Ultrasound") print("Histopatoloji veri artırma örnekleri:") visualizeaugmentation(histopathimages, "Histopatoloji")

=============================================================================

6. Model Tanımları: MobileViT Blok ve Sınıflandırma Modeli Oluşturma

=============================================================================

from tensorflow.keras import regularizers

def mobilevitblock(x, transformerdim=64, mlpdim=128, patchsize=2, numheads=2, dropoutrate=0.1): y = tf.keras.layers.Conv2D(transformerdim, kernelsize=3, padding='same', activation='relu')(x) H, W = y.shape[1], y.shape[2] yflat = tf.keras.layers.Reshape((H * W, transformerdim))(y) attnoutput = tf.keras.layers.MultiHeadAttention(numheads=numheads, keydim=transformerdim, dropout=dropoutrate)(yflat, yflat) yflat = tf.keras.layers.Add()([yflat, attnoutput]) yflat = tf.keras.layers.LayerNormalization()(yflat) mlpoutput = tf.keras.layers.Dense(mlpdim, activation='relu')(yflat) mlpoutput = tf.keras.layers.Dense(transformerdim)(mlpoutput) yflat = tf.keras.layers.Add()([yflat, mlpoutput]) yflat = tf.keras.layers.LayerNormalization()(yflat) yreshaped = tf.keras.layers.Reshape((H, W, transformerdim))(yflat) output = tf.keras.layers.Conv2D(x.shape[-1], kernelsize=1, padding='same')(y_reshaped) return output

def createmobilevitbranch(inputshape=(128,128,3)): inputs = tf.keras.Input(shape=inputshape) x = tf.keras.layers.Conv2D(32, kernelsize=3, strides=2, padding='same', activation='relu', kernelregularizer=regularizers.l2(0.001))(inputs) x = tf.keras.layers.BatchNormalization()(x) x = mobilevitblock(x, transformerdim=64, mlpdim=128, patchsize=2, numheads=2, dropoutrate=0.1) x = tf.keras.layers.Conv2D(64, kernelsize=3, strides=2, padding='same', activation='relu', kernelregularizer=regularizers.l2(0.001))(x) x = tf.keras.layers.BatchNormalization()(x) x = mobilevitblock(x, transformerdim=80, mlpdim=160, patchsize=2, numheads=2, dropoutrate=0.1) x = tf.keras.layers.GlobalAveragePooling2D()(x) x = tf.keras.layers.BatchNormalization()(x) x = tf.keras.layers.Dense(256, activation='relu', kernelregularizer=regularizers.l2(0.001))(x) x = tf.keras.layers.Dropout(0.5)(x) # Sınıflandırma başlığı ekleyelim: output = tf.keras.layers.Dense(1, activation='sigmoid', kernelregularizer=regularizers.l2(0.001))(x) model = tf.keras.Model(inputs, output) model.compile(optimizer=Adam(learningrate=1e-4), loss='binarycrossentropy', metrics=['accuracy', tf.keras.metrics.AUC(), tf.keras.metrics.Precision(), tf.keras.metrics.Recall()]) return model

=============================================================================

7. Bölüm: K-Fold Çapraz Doğrulama ile Model Eğitimi (Tek Modalite) – Batch Size = 8

=============================================================================

def crossvalidatemodel(modelbuilder, images, labels, folds=5, batchsize=8, epochs=10): skf = StratifiedKFold(nsplits=folds, shuffle=True, randomstate=42) foldno = 1 histories = [] cvmetrics = [] for trainindex, valindex in skf.split(images, labels): print(f"\n--- Fold {foldno} ---") Xtrain, Xval = images[trainindex], images[valindex] ytrain, yval = labels[trainindex], labels[val_index]

traindatagen = ImageDataGenerator( rotationrange=20, widthshiftrange=0.2, heightshiftrange=0.2, shearrange=0.2, zoomrange=0.2, horizontalflip=True, fillmode='nearest' ) valdatagen = ImageDataGenerator() traingenerator = traindatagen.flow(Xtrain, ytrain, batchsize=batchsize) valgenerator = valdatagen.flow(Xval, yval, batchsize=batch_size)

model = modelbuilder() callbacks = [ EarlyStopping(monitor='valloss', patience=5, restorebestweights=True, verbose=1), ReduceLROnPlateau(monitor='valloss', factor=0.5, patience=3, minlr=1e-6, verbose=1) ] history = model.fit( traingenerator, epochs=epochs, validationdata=val_generator, callbacks=callbacks, verbose=1 )

yvalpredprob = model.predict(Xval) yvalpred = (yvalpredprob > 0.5).astype(int).flatten() acc = accuracyscore(yval, yvalpred) prec = precisionscore(yval, yvalpred) rec = recallscore(yval, yvalpred) f1 = f1score(yval, yvalpred) fpr, tpr, = roccurve(yval, yvalpredprob) rocauc = auc(fpr, tpr) metrics = {'fold': foldno, 'accuracy': acc, 'precision': prec, 'recall': rec, 'f1': f1, 'rocauc': rocauc} cvmetrics.append(metrics) print(f"Fold {fold_no} metrikleri: {metrics}")

plt.figure(figsize=(12,5)) plt.subplot(1,2,1) plt.plot(history.history['accuracy'], label='Eğitim Doğruluğu') plt.plot(history.history['valaccuracy'], label='Doğrulama Doğruluğu') plt.title(f'Fold {foldno} Doğruluk') plt.xlabel('Epoch') plt.ylabel('Doğruluk') plt.legend() plt.subplot(1,2,2) plt.plot(history.history['loss'], label='Eğitim Kaybı') plt.plot(history.history['valloss'], label='Doğrulama Kaybı') plt.title(f'Fold {foldno} Kayıp') plt.xlabel('Epoch') plt.ylabel('Kayıp') plt.legend() plt.show()

plt.figure() plt.plot(fpr, tpr, label=f'Fold {foldno} ROC (AUC = {rocauc:.2f})') plt.plot([0,1],[0,1],'k--') plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title(f'Fold {fold_no} ROC Eğrisi') plt.legend() plt.show()

cm = confusionmatrix(yval, yvalpred) sns.heatmap(cm, annot=True, fmt="d", cmap="Blues") plt.title(f'Fold {fold_no} Confusion Matrix') plt.xlabel("Predicted") plt.ylabel("True") plt.show()

histories.append(history) foldno += 1 tf.keras.backend.clearsession() return histories, cv_metrics

print("\n--- Mamogram Modeli için 5-Fold Çapraz Doğrulama ---") mamogramhistories, mamogramcvmetrics = crossvalidatemodel(createmobilevitbranch, mamogramimages, mamogramlabels, epochs=10) print("\nMamogram CV Metrikleri:", mamogramcv_metrics)

print("\n--- Ultrasound Modeli için 5-Fold Çapraz Doğrulama ---") ultrasoundhistories, ultrasoundcvmetrics = crossvalidatemodel(createmobilevitbranch, ultrasoundimages, ultrasoundlabels, epochs=10) print("\nUltrasound CV Metrikleri:", ultrasoundcv_metrics)

print("\n--- Histopatoloji Modeli için 5-Fold Çapraz Doğrulama ---") histopathhistories, histopathcvmetrics = crossvalidatemodel(createmobilevitbranch, histopathimages, histopathlabels, epochs=10) print("\nHistopatoloji CV Metrikleri:", histopathcv_metrics)

=============================================================================

8. Bölüm: Final Ensemble Model Eğitimi (Tüm Veriler Üzerinde) – Batch Size = 8

=============================================================================

Final eğitim için üç modalitenin örnek sayıları farklı olabilir.

Bu durumda, ortak (rastgele) alt küme seçimi yaparak örnek sayısını eşitleyelim.

minsamples = min(len(mamogramimages), len(ultrasoundimages), len(histopathimages)) print("Ortak örnek sayısı:", min_samples)

indicesm = np.random.choice(len(mamogramimages), minsamples, replace=False) indicesu = np.random.choice(len(ultrasoundimages), minsamples, replace=False) indicesh = np.random.choice(len(histopathimages), min_samples, replace=False)

mamogramimageseq = mamogramimages[indicesm] ultrasoundimageseq = ultrasoundimages[indicesu] histopathimageseq = histopathimages[indicesh] mamogramlabelseq = mamogramlabels[indicesm] # Ground truth olarak mamogram etiketleri kullanılıyor

def createensemblemodelensemble(): branchmamogram = createmobilevitbranch(inputshape=(128,128,3)) branchultrasound = createmobilevitbranch(inputshape=(128,128,3)) branchhistopath = createmobilevitbranch(inputshape=(128,128,3)) inputmamogram = tf.keras.Input(shape=(128,128,3)) inputultrasound = tf.keras.Input(shape=(128,128,3)) inputhistopath = tf.keras.Input(shape=(128,128,3)) featmamogram = branchmamogram(inputmamogram) featultrasound = branchultrasound(inputultrasound) feathistopath = branchhistopath(inputhistopath) merged = concatenate([featmamogram, featultrasound, feathistopath]) x = Dense(512, activation='relu', kernelregularizer=regularizers.l2(0.001))(merged) x = Dropout(0.5)(x) x = Dense(256, activation='relu', kernelregularizer=regularizers.l2(0.001))(x) x = Dropout(0.5)(x) output = Dense(1, activation='sigmoid', kernelregularizer=regularizers.l2(0.001))(x) model = tf.keras.Model(inputs=[inputmamogram, inputultrasound, inputhistopath], outputs=output) model.compile(optimizer=Adam(learningrate=1e-4), loss='binarycrossentropy', metrics=['accuracy', tf.keras.metrics.AUC(), tf.keras.metrics.Precision(), tf.keras.metrics.Recall()]) return model

ensemblemodel = createensemblemodelensemble() ensemblemodel.fit( [mamogramimageseq, ultrasoundimageseq, histopathimageseq], mamogramlabelseq, validationsplit=0.2, epochs=50, batchsize=8, callbacks=[ EarlyStopping(monitor='valloss', patience=5, restorebestweights=True, verbose=1), ReduceLROnPlateau(monitor='valloss', factor=0.5, patience=3, minlr=1e-6, verbose=1) ], verbose=1 )

MODELSAVEPATH = os.path.join("/content/gdrive/MyDrive/memekanserimodelleri", "finalensemblemodel.keras") os.makedirs(os.path.dirname(MODELSAVEPATH), existok=True) ensemblemodel.save(MODELSAVEPATH) print(f"Final Ensemble Model kaydedildi: {MODELSAVEPATH}")

=============================================================================

9. Bölüm: Final Model Performans Değerlendirmesi ve Eğrileri

=============================================================================

Test setine bölünme (rastgele alt küme kullanılarak)

X1 = mamogramimageseq X2 = ultrasoundimageseq X3 = histopathimageseq y = mamogramlabelseq

X1train, X1test, X2train, X2test, X3train, X3test, ytrain, ytest = traintestsplit( X1, X2, X3, y, testsize=0.2, randomstate=42 )

Final model eğitimi ve geçmişini kaydetme

finalhistory = ensemblemodel.fit( [X1train, X2train, X3train], ytrain, validationdata=([X1test, X2test, X3test], ytest), epochs=50, # veya önceki eğitimde kullanılan epoch sayısı batchsize=8, # veya önceki eğitimde kullanılan batch size callbacks=[ EarlyStopping(monitor='valloss', patience=5, restorebestweights=True, verbose=1), ReduceLROnPlateau(monitor='valloss', factor=0.5, patience=3, min_lr=1e-6, verbose=1) ], verbose=1 )

evalresults = ensemblemodel.evaluate([X1test, X2test, X3test], ytest, verbose=1) print("Test Loss:", evalresults[0]) print("Test Accuracy:", evalresults[1])

ypredprob = ensemblemodel.predict([X1test, X2test, X3test]) ypred = (ypred_prob > 0.5).astype(int).flatten()

from sklearn.metrics import accuracyscore, precisionscore, recallscore, f1score, roccurve, auc, confusionmatrix

acc = accuracyscore(ytest, ypred) prec = precisionscore(ytest, ypred) rec = recallscore(ytest, ypred) f1 = f1score(ytest, ypred) fpr, tpr, thresholds = roccurve(ytest, ypredprob) rocauc = auc(fpr, tpr) cm = confusionmatrix(ytest, ypred)

print("Test Accuracy:", acc) print("Test Precision:", prec) print("Test Recall:", rec) print("Test F1 Score:", f1) print("Test ROC AUC:", roc_auc)

plt.figure(figsize=(15,5)) plt.subplot(1,3,1) plt.plot(finalhistory.history['accuracy'], label='Eğitim Accuracy') plt.plot(finalhistory.history['val_accuracy'], label='Doğrulama Accuracy') plt.title('Final Model Accuracy Eğrisi') plt.xlabel('Epoch') plt.ylabel('Accuracy') plt.legend()

plt.subplot(1,3,2) plt.plot(finalhistory.history['loss'], label='Eğitim Loss') plt.plot(finalhistory.history['val_loss'], label='Doğrulama Loss') plt.title('Final Model Loss Eğrisi') plt.xlabel('Epoch') plt.ylabel('Loss') plt.legend()

plt.subplot(1,3,3)

Check for all possible 'auc' keys

for key in finalhistory.history.keys(): if 'auc' in key: auckey = key break # Exit loop once the 'auc' key is found else: # Raise an error if no 'auc' key is found raise KeyError("AUC metric not found in history")

plt.plot(finalhistory.history[auckey], label='Eğitim AUC') plt.plot(finalhistory.history['val' + auc_key], label='Doğrulama AUC') plt.title('Final Model AUC Eğrisi') plt.xlabel('Epoch') plt.ylabel('AUC') plt.legend() plt.show()

plt.figure() plt.plot(fpr, tpr, label="ROC curve (AUC = {:.2f})".format(roc_auc)) plt.plot([0, 1], [0, 1], "k--") plt.xlim([0, 1]) plt.ylim([0, 1.05]) plt.xlabel("False Positive Rate") plt.ylabel("True Positive Rate") plt.title("Final Ensemble Model ROC Eğrisi") plt.legend(loc="lower right") plt.show()

plt.figure() sns.heatmap(cm, annot=True, fmt="d", cmap="Blues") plt.title("Final Ensemble Model Confusion Matrix") plt.xlabel("Predicted") plt.ylabel("True") plt.show()

=============================================================================

9. Bölüm: Gradio Web Arayüzü ile Tahmin

=============================================================================

def predictensemble(mamogramimg, ultrasoundimg, histopathimg): mamogramimg = cv2.resize(mamogramimg, (128,128)) / 255.0 ultrasoundimg = cv2.resize(ultrasoundimg, (128,128)) / 255.0 histopathimg = cv2.resize(histopathimg, (128,128)) / 255.0 mamogramimg = np.expanddims(mamogramimg, axis=0) ultrasoundimg = np.expanddims(ultrasoundimg, axis=0) histopathimg = np.expanddims(histopathimg, axis=0) pred = ensemblemodel.predict([mamogramimg, ultrasoundimg, histopath_img]) result = "Malignant" if pred[0][0] > 0.5 else "Benign" confidence = float(pred[0][0]) return {"Tahmin": result, "Güven": confidence}

interface = gr.Interface( fn=predict_ensemble, inputs=[ gr.Image(label="Mamogram Görüntüsü", type="numpy"), # Remove 'shape' and set type to 'numpy' gr.Image(label="Ultrasound Görüntüsü", type="numpy"), # Remove 'shape' and set type to 'numpy' gr.Image(label="Histopatoloji Görüntüsü", type="numpy") # Remove 'shape' and set type to 'numpy' ], outputs=[ gr.Label(label="Tahmin"), gr.Number(label="Güven") ], title="Meme Kanseri Tespiti - Ensemble Model", description="Mamogram, Ultrasound ve Histopatoloji görüntülerini yükleyin; ensemble modelimiz kanser tespiti yapsın." ) interface.launch(share=True)