「糖尿病網膜症の段階を予測して眼の盲目を防ぐ」
Predict and prevent blindness in diabetic retinopathy stages.
はじめに
糖尿病性網膜症は、網膜の血管に変化を引き起こす眼の状態です。無治療のまま放置すると、視力の喪失につながります。そのため、糖尿病性網膜症の段階を検出することは、目の失明を防ぐために重要です。このケーススタディは、糖尿病性網膜症の症状から目の失明を検出することについてのもので、データはさまざまな撮影条件で眼底カメラ(眼の後ろを写真に撮るカメラ)を使用して、さまざまな訓練された臨床専門家によって田舎の地域から収集されました。これらの写真は、2019年にKaggleが行ったコンペティション(APTOS 2019 Blindness Detection)で糖尿病性網膜症の段階を検出するために使用され、私たちのデータは同じKaggleのコンペティションから取得されました。この糖尿病性網膜症の早期検出は、治療を迅速化し、視力の喪失のリスクを大幅に減らすのに役立ちます。
訓練された臨床専門家の手作業による介入は、特に発展途上国では時間と労力がかかります。したがって、このケーススタディの主な目的は、効率的な技術を使用して状態の重症度を検出し、失明を防止することです。私たちは、深層学習の技術を実装して、状態の分類に効果的な結果を得るために取り組んでいます。
学習目標
- 糖尿病性網膜症の理解:眼の状態と視力への影響について学び、早期検出の重要性を強調します。
- 深層学習の基礎:深層学習の基礎を探求し、糖尿病性網膜症の診断における関連性を理解します。
- データの前処理と拡張:ディープラーニングモデルのトレーニングのためにデータセットを効果的に準備し、強化する方法を理解します。
- モデルの選択と評価:重症度分類のためのディープラーニングモデルの選択と性能評価の方法を学びます。
- 実用的な展開:Flaskを使用して最適なモデルの展開と実世界での予測を実現します。
この記事はデータサイエンスブログマラソンの一環として公開されました。
- 「UNETアーキテクチャの包括的なガイド | 画像セグメンテーションのマスタリング」
- ChatGPT コードインタプリターを使用できない 4 つの方法、それらがアナリティクスを乱す
- Apache BeamにおけるParDoとDoFnの実装の詳細
ビジネスの問題
ここでは、人の状態の重症度が5つのカテゴリに分類されます。つまり、人は重症度レベルのいずれか1つで認識されます。
ビジネスの制約事項
医療分野では正確性と解釈可能性が非常に重要です。間違った予測は人々の命を奪う可能性があるため、厳格なレイテンシの心配はありませんが、結果については正確でなければなりません。
データセットの説明
データセットには、訓練された臨床専門家が各画像を糖尿病性網膜症の重症度に基づいて以下のように分類した3,662枚のラベル付き網膜画像が含まれています。
0 — 糖尿病性網膜症なし
1 — 軽度
2 — 中程度
3 — 重度
4 — 増殖性糖尿病性網膜症
上記の表は、データセットの画像が糖尿病性網膜症の段階のいずれかで識別されていることを示しています。
パフォーマンスメトリック
評価メトリックとして、多クラス分類のために二次加重カッパと混同行列を使用しています。
カッパは、実際のラベルと予測されたラベル間の一致(類似性)を測定します。カッパスコアが1.0の場合、予測と実際のラベルが同じであることを示し、-1のカッパスコアは予測が実際のラベルから大きく離れていることを示します。このメトリックの目標は、0.6以上のカッパスコアを得ることです。
カッパメトリックは、医療診断において重要な役割を果たします。-1のスコアの場合、予測ラベルと実際のラベラーがどれだけ似ているかを示し、一致しない場合にペナルティを課します。たとえば、私たちの場合、予測ラベルが0で実際のラベルが1である場合、これは患者にとって深刻な問題であり、追加の診断は推奨されません。
混同行列は、分類モデルのパフォーマンスを評価するために使用されます。この行列は、実際の目標値とモデルによって予測された目標値を比較します。これにより、分類モデルのパフォーマンスがどれくらい良いか、どのような種類のエラーが発生するかを包括的に把握することができます。
探索的データ分析と前処理
棒グラフをプロットしてデータの分布を確認しましょう。
v=df['diagnosis'].value_counts().plot(kind='bar')
上記のプロットから、データが明らかに不均衡であることがわかります。不正確な結果を防ぐために、データをバランスさせる必要があります。
データセットの一様な分布を得るために、クラスの重みを適用することができます。
トレーニングデータセットには3,662枚の画像しか含まれていないため、Kaggleから提供されたデータセットは非常に小さいです。小さなデータセットでトレーニングするため、オーバーフィットが望ましいです。そのため、前処理はデータセットを増やすことによってパフォーマンスを向上させるために重要な役割を果たします。したがって、データ拡張に取り組んでデータセットを改善します。データ拡張の前に、画像の状態をチェックする必要があります。データはさまざまなソースから収集されているため、画像が非常に暗いか、余分な黒い背景があるか、さまざまな画像サイズの画像かどうかなどを確認する必要があります。したがって、画像の品質を均一に保つために、画像にスムージング技術を適用する必要があります。余分な黒い背景のトリミング、画像の典型的なサイズにリサイズなど。
上記から、データセットには水平トリミング、垂直トリミング、および余分な黒い領域を含む異なるサイズの画像が含まれていることがわかります。
以下のスムージング技術を適用して、すべての画像を均一な品質にします。
トリミング関数
→ トリミング関数 – 画像の周りの余分な暗い部分を除去するために使用します。
def crop(img,tol=7):
# tolは許容度です
'''
このトリミング関数は、画像の周りの暗い部分を除去するために使用されます。
'''
if img.ndim==2:
# GRAY画像のトリミングに使用されるループです
mask=img>tol
return img[np.ix_(mask.any(1),mask.any(0))]
elif img.ndim==3:
# カラー画像のトリミングに使用されるループです
grayimg=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
mask=grayimg>tol
shap=img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]
if shap==0:
# 画像があまりにも暗いため、すべてをトリミングします
return img
else:
img0=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]
img1=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]
img2=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]
img=np.stack([img0,img1,img2],axis=-1)
return img #import csv
以下の図は、関数を適用した後、周りの暗い部分をトリミングして得られた画像を示しています。
→ サークルトリミング関数は、中心からの参照を使用して画像を円形にトリミングします。
def circlecrop(img):
'''
画像を中心から円形にトリミングするために使用されます。
'''
h,w,d= img.shape
x = int(w/2)
y = int(h/2)
r = np.amin((x,y))
circle_img = np.zeros((h,w), np.uint8)
cv2.circle(circle_img, (x,y), int(r), 1, thickness=-1)
img = cv2.bitwise_and(img, img, mask=circle_img)
return img
以下の図は、円形トリミング関数を適用した後の画像を示しています。
Ben Grahamの関数
→ Ben Grahamの関数-画像の明るさを向上させるために適用されます。
def ben(img,sigmaX=10):
'''
照明条件を改善するためのBen Grahamの方法。
'''
image=cv2.addWeighted( img,4, cv2.GaussianBlur( img , (0,0) , sigmaX) ,-4 ,128)
return image
以下の図は、ベン・グラハムの関数を適用した後、画像の照明条件が改善されたことを示しています。
上記の関数を適用した後の前処理された網膜画像を確認しましょう。
データセットが非常に小さいため、オーバーフィッティングの可能性があります。このシナリオを克服するために、トレーニングデータを増やす必要があります。水平反転、垂直反転、画像の回転、拡大、明るさの設定などの拡張技術を使用してデータを増やします。
from keras_preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(horizontal_flip=True, vertical_flip=True, rotation_range=360,
brightness_range=[0.5, 1],
zoom_range=0.2, rescale=1./255., validation_split=0.25)
validation_datagen = ImageDataGenerator(rescale=1./255)
train_generator = datagen.flow_from_dataframe(
dataframe=df,
directory="prep",
x_col="add",
y_col="diagnosis",
subset="training",
batch_size=12,
seed=42,
shuffle=True,
class_mode="categorical",
target_size=(256, 256))
バリデーション分割を0.25として使用したため、2,747のトレーニング画像と915のバリデーション画像を取得します。
ここでは、各画像が水平反転、垂直反転、回転範囲、明るさ範囲、ズーム範囲の5つのテクニックを使用して5回複製されます。
ディープラーニングモデル
まず、シンプルなCNNアーキテクチャでベースラインモデルを構築します。
inp = Input(shape=(256, 256, 3))
x = Conv2D(32, (3, 3), activation='relu')(inp)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Dropout(0.5)(x)
x = Flatten()(x)
x = BatchNormalization()(x)
x = Dense(5, activation='softmax')(x)
上記のモデルでは、0.554のカッパスコアが得られましたが、これは状態の予測には受け入れられません。
高いカッパスコアを達成するために、転移学習に進みます。
VGG-16
model_vgg16 = VGG16(weights='imagenet', include_top=False, input_shape=(256, 256, 3))
x = GlobalAveragePooling2D()(model_vgg16.layers[-1].output)
x = Dropout(0.5)(x)
x = Dense(5, activation='softmax')(x)
→トレーニングコーエンカッパスコア:0.913
→トレーニング正確度スコア:0.817
上記のモデルでは、0.913のカッパスコアが得られました。
DENSENET
modeldense = DenseNet121(weights='imagenet', include_top=False, input_shape=(256, 256, 3))
x = GlobalAveragePooling2D()(modeldense.layers[-1].output)
x = Dropout(0.5)(x)
x = Dense(5, activation='softmax')(x)
→トレーニングコーエンカッパスコア:0.933
→トレーニング正確度スコア:0.884
上記のモデルでは、0.933のカッパスコアが得られました。
RESNET
modelres152 = ResNet152(weights='imagenet', include_top=False, input_shape=(256, 256, 3))
x = GlobalAveragePooling2D()(modelres152.layers[-1].output)
x = Dropout(0.5)(x)
x = Dense(5, activation='softmax')(x)
→トレーニングコーエンカッパスコア:0.910
→トレーニング正確度スコア:0.844
上記のモデルでは、0.91のカッパスコアが得られました。
EFFICIENTNET
EEfficientNetB0、B3、B4、およびB7などのさまざまな効率的なモデルを実装した後、EfficientNetB7を使用してより良い結果を生成することができます。
modeleffB7 = EfficientNetB7(weights='imagenet', include_top=False, input_shape=(256, 256, 3))
x = GlobalAveragePooling2D()(modeleffB7.layers[-1].output)
x = Dropout(0.5)(x)
x = Flatten()(x)
x = Dense(5, activation='softmax')(x)
→訓練のCohen Kappaスコア:0.877
→訓練の正解率スコア:0.838
上記のモデルから、Cohen Kappaスコアが0.877であることがわかります
XCEPTION
modelxcep = Xception(weights='imagenet', include_top=False, input_shape=(256, 256, 3))
x = GlobalAveragePooling2D()(modelxcep.layers[-1].output)
x = Dropout(0.5)(x)
x = Flatten()(x)
x = Dense(5, activation='softmax')(x)
→訓練のCohen Kappaスコア:0.925
→訓練の正解率スコア:0.854
上記のモデルから、Cohen Kappaスコアが0.925であることがわかります
上記のモデルから、Densetモデルの方がより良いKappaスコアを得ることが分かります。したがって、私たちはDensetモデルを最良のモデルとして選び、ステージの予測に進みます。
最良のモデルを使用した予測
最良のモデルを使用してステージを予測します:
X = '/content/00a8624548a9.png'
img = cv2.imread(X)
img = crop(img)
img = cv2.resize(img, (256, 256), interpolation=cv2.INTER_AREA)
img = circlecrop(img)
img = ben(img)
img = np.reshape(img, [1, 256, 256, 3])
cd = ImageDataGenerator(horizontal_flip=True, vertical_flip=True,
rotation_range=360, brightness_range=[0.5, 1],
zoom_range=0.2, rescale=1./255)
cg = cd.flow(img, batch_size=1)
tp = model.predict(cg)
op = np.argmax(tp)
if op == 0:
matter = "ステージ0-糖尿病網膜症なし"
elif op == 1:
matter = "ステージ1-軽度"
elif op == 2:
matter = "ステージ2-中等度"
elif op == 3:
matter = "ステージ3-重度"
elif op == 4:
matter = "ステージ4-増殖性糖尿病網膜症"
print(matter)
上記の画像から、最良のモデルが糖尿病網膜症のステージを予測していることがわかります。
Flaskを使用したモデルの展開
モデルを展開するためにFlaskを使用しました。これにより、アップロードされた網膜画像の色覚異常のステージを予測することができます。以下は展開されたモデルの実行インスタンスのビデオです。
結論
このブログでは、深層学習が糖尿病網膜症の検出と視力の喪失予防における変革の力を示しています。早期発見と正確な重症度分類により、AIは患者の結果を大幅に改善することができます。Flaskを使用したモデルの展開により、これらの技術の現実世界での適用可能性がハイライトされ、医療設定での実用性が示されています。
拡張技術とモデルの改善に関する継続的な研究により、診断能力がさらに向上するでしょう。AIの潜在能力を活用することで、医学的な診断を革新し、より健康な未来を築く道を開拓することができます。
- VGG-16、DENSENET、RESNET、EFFICIENTNET、XCEPTIONなどの深層学習モデルは、糖尿病網膜症の重症度を効果的に分類しています。
- 最も性能の良いモデルであるDENSENETは、高いKappaスコアを達成し、正確な予測能力を示しています。
- データの前処理と拡張は、モデルの性能と汎化能力を向上させる上で重要です。
- Flaskの展開は、実世界のシナリオでの深層学習の実用的な適用性を示し、効率的な診断と治療を促進します。
- 拡張技術とモデルの改善に関する継続的な研究は、診断の正確性をさらに向上させ、AIを活用した医学的な診断を進化させる可能性を秘めています。
今後の課題
- より多くの拡張技術を実装することができます。
- モデルにさまざまな畳み込み層を試すことができます。
- トレーニング用のさらなる網膜画像を収集する必要があります。
よくある質問
参考文献
- https://github.com/btgraham/SparseConvNet/blob/kaggle_Diabetic_Retinopathy_competition/competitionreport.pdf
- https://arxiv.org/abs/1905.11946
- https://arxiv.org/abs/0704.1028
- https://www.kaggle.com/xhlulu/aptos-2019-densenet-keras-starter
- https://www.kaggle.com/c/aptos2019-blindness-detection/discussion/108065
この記事に掲載されているメディアはAnalytics Vidhyaの所有物ではなく、著者の裁量で使用されています。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles