本文主要说明神经网络的构建,共21个层级
def build_model(input_shape):
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=input_shape),
layers.BatchNormalization(),
layers.MaxPooling2D((2, 2)),
layers.Dropout(0.2),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D((2, 2)),
layers.Dropout(0.3),
layers.Conv2D(128, (3, 3), activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D((2, 2)),
layers.Dropout(0.4),
layers.Conv2D(256, (3, 3), activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D((2, 2)),
layers.Dropout(0.5),
layers.Flatten(),
layers.Dense(512, activation='relu'),
layers.BatchNormalization(),
layers.Dropout(0.5),
layers.Dense(1, activation='sigmoid')
])
optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)
model.compile(
optimizer=optimizer,
loss='binary_crossentropy',
metrics=[
'accuracy',
tf.keras.metrics.Precision(name='precision'),
tf.keras.metrics.Recall(name='recall'),
tf.keras.metrics.AUC(name='auc')
]
)
return model
咱们数一下这个神经网络总共有多少层(按代码里的顺序一层一层数):
这个神经网络总共是 21 层,可以分成几类:
Conv2D 是神经网络里专门用来 “看图片” 的 “放大镜工具”,全称是 “二维卷积层”,特别擅长从图片中抓特征(比如边缘、斑点、纹理这些)。
假设你有一张 X 光片,Conv2D 就像一个小窗口(比如 3x3 像素大小),会从图片左上角开始,一点点往右、往下滑动,每到一个位置就 “扫描” 这个小窗口里的像素,计算出一个新的数值 —— 这个数值就代表了这个区域的某个特征(比如 “这里有一条边缘”“这里有块阴影”)。
代码里的 Conv2D(32, (3, 3), ...) 可以拆成两部分理解:
经过 Conv2D 处理后,一张图片会变成 32 张 “特征图”—— 每张特征图上都是用对应的 “放大镜” 抓出来的特征,方便后面的层进一步分析。
简单说,Conv2D 的作用就是:用多个小窗口扫描图片,把隐藏的特征(比如肺炎的阴影)“显形”,是神经网络 “看懂” 图片的核心工具。
(3, 3) 这个卷积窗口大小是程序员提前设定好的固定值,不是自动计算或随机生成的。它就像一个 “标准工具尺寸”,是人为选定后写死在代码里的。
而 32 个卷积核(“放大镜”)的具体识别能力,则是在训练过程中 “学” 出来的,不是一开始就固定的:
简单说:
整个过程就像:老师先规定 “必须用 3×3 厘米的放大镜观察”(固定窗口),然后让 32 个学生用这个工具去看大量图片,最后每个学生自然练出了不同的观察重点(自动学到不同特征)。
这三行代码是神经网络里的 “辅助工具”,配合前面的卷积层一起工作,让网络学得更好、更稳定。用大白话一个个解释:
可以理解成 “数据标准化工具”,作用是让每层处理的数据 “保持稳定”。
比如:
简单说:让数据更规整,网络学起来更轻松。
“压缩工具”,专门给图片 “瘦身”,保留关键信息的同时减少计算量。
(2, 2) 表示把图片按 2x2 的小方块划分,每个方块里只保留最亮(数值最大)的那个像素,其他的丢掉。
比如:
简单说:去粗取精,让网络跑得更快。
“防作弊工具”,故意让一部分 “神经细胞” 暂时 “休息”,避免网络 “死记硬背”。
0.2 表示随机让 20% 的细胞不工作。
比如:
简单说:防止学歪,让网络更会举一反三。
这三个工具是卷积层的 “黄金搭档”:
layers.Dropout(0.2) 就像给神经网络 “故意制造一点小麻烦”,防止它 “死记硬背” 答案。
这么做的目的是:逼网络学 “通用规律”,而不是 “死记硬背”。
举个例子:
如果网络学 X 光片时,发现 “某张肺炎片角落有个小黑点”,没 dropout 的话,它可能偷懒只记 “有小黑点就是肺炎”(其实那是污渍)。
但有了 dropout(随机关掉部分细胞),它没法总依赖 “小黑点” 这个特征(因为记这个特征的细胞可能被关掉),只能被迫去学更靠谱的规律(比如阴影的形状、分布)。
最容易出现的问题是 “过拟合”—— 网络把训练时的图片 “背得滚瓜烂熟”,但换一张新图片就傻了。
比如:
没有 dropout 的网络,就像死记硬背考试答案的学生 —— 考题稍变就不会做了;
有 dropout 的网络,就像真正理解知识点的学生 —— 不管题目怎么变,都能答对。
Dropout(0.2) 就是通过 “随机让 20% 细胞休息”,防止网络 “走捷径、死记硬背”,逼着它学更通用的规律,这样面对新图片时判断更准。
不用它,网络容易 “学傻”,只会应付老图片,不会处理新情况。
假设前面的卷积层是 “侦察兵”,各自盯着图片里的小细节(比如边缘、颜色块、纹理),每个侦察兵只负责自己那一小块信息。
到了全连接层,就像把所有侦察兵召集到一个大会议室。这一层里的每个 “决策者”(神经元)都会和所有侦察兵聊一遍 —— 也就是接收前面所有层的信息,一个都不落下。
比如识别猫的时候:
之所以叫 “全连接”,就是因为这一层的每个神经元和上一层的所有神经元都有连接,没有信息死角。它的作用就是把零散的细节拼成一个完整的判断。
layers.Dense(512, activation='relu'):
Dense
:就是 “全连接层”,意思是这一层的每个 “神经细胞” 都会和上一层所有的特征产生连接,就像一个会议室里,每个专家都要听取前面所有人的汇报。512
:表示这个 “整合中心” 有 512 个 “专家”(神经细胞),每个专家负责关注不同的特征组合(比如 “阴影形状 + 位置”“边缘清晰度 + 大小”)。activation='relu'
:相当于 “过滤器”,只让有价值的特征组合通过(比如 “这个阴影形状很可能是肺炎”),过滤掉无意义的信息(比如 “图片角落的小噪点”)。这部分是神经网络的 “决策层”,负责把前面提取到的图片特征汇总起来,最终判断 “是不是肺炎”。用大白话一个个解释:
“整理工”—— 把前面层层处理得到的特征(像一堆二维的矩阵)全部摊平,变成一条长长的 “特征数字链”。
比如:前面最后一层可能输出一个 7×7×256 的特征矩阵(类似一堆叠起来的小图片),经过 Flatten() 处理后,会变成一个 7×7×256=12544 个数字组成的一维列表。
作用:把复杂的多维特征 “捋顺”,方便后面的 “决策专家” 处理。
“特征整合专家团”——512 个 “专家” 一起分析前面摊平的特征链,找出最关键的信息。
作用:把零散的特征(比如 “有阴影”“边缘模糊”)整合成更高层次的判断依据(比如 “这些特征组合起来像肺炎”)。
“稳定器”—— 和前面卷积块里的作用一样,让 512 个专家的 “意见” 更统一、更稳定。
比如:避免某个专家因为特征数值波动(比如某次特征值特别大)而过度影响结果,让判断更可靠。
“防偏见工具”—— 随机让 50% 的 “专家” 暂时不发表意见,防止网络过度依赖某几个专家的判断。
比如:如果某个专家错误地认为 “所有圆形阴影都是肺炎”,dropout 会偶尔让它闭嘴,逼网络参考其他专家的意见,避免 “偏见” 影响最终结果。
“最终裁判”—— 综合所有专家的有效意见,给出最终结论。
作用:给出一个明确的二分类判断(是 / 不是肺炎)。
这部分就像 “医院会诊” 流程:
layers.BatchNormalization() 可以理解成神经网络里的 “数据标准化小助手”,作用是让每层处理的数据 “保持稳定”,避免因为数据忽大忽小给网络添乱。
举个生活例子:
假设你在玩拼图,前几包拼图的碎片都是 5 厘米大小,突然来了一包 5 米大的碎片 —— 你肯定会懵,不知道怎么拼。
神经网络也一样,如果上一层输出的数据忽大忽小(比如一会儿是 0.1、0.2,一会儿是 100、200),下一层就会 “confusion”,学起来很费劲。
BatchNormalization 就像一个 “调解员”:
它会把每层的数据 “重新整理” 一下,让数据都集中在一个合理的范围(比如大部分在 0 附近波动),不会出现特别大或特别小的极端值。
比如:
简单说:它让数据变得 “规矩”,让网络学起来更轻松、更稳定,不容易因为数据波动而 “学偏”。
# 使用更稳定的优化器
optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)
model.compile(
optimizer=optimizer,
loss='binary_crossentropy',
metrics=[
'accuracy',
tf.keras.metrics.Precision(name='precision'),
tf.keras.metrics.Recall(name='recall'),
tf.keras.metrics.AUC(name='auc')
]
)
这部分代码是给神经网络 “设定学习规则”,就像给学生制定 “学习方法” 和 “考试标准”。
“学习节奏控制器”
作用:让网络在训练时,能慢慢修正错误,找到正确的 “判断规律”。
2.将优化器交给模型
optimizer=optimizer 看起来像绕口令,其实很简单:就是把前面定义好的 “学习方法”(那个叫 Adam 的优化器)正式 “交给” 模型。
打个比方:
说白了,就是把准备好的 “学习节奏控制器” 正式安装到模型里,让模型训练时能按这个方法调整自己的 “学习策略”。
“设定训练目标和评分标准”
就像告诉学生:“这次训练要达到什么目标,用什么标准判断你学得好不好”。
二分类任务(比如 “是肺炎” 还是 “不是肺炎”)的专用 “错题计算方式”。值越小,说明网络当前的判断和实际结果越接近(错题越少)。
用来衡量网络学得好不好的具体指标(相当于考试的不同题型得分):
这部分代码的作用是:
就像给学生说:“用这种方法慢慢学,错了就小幅度改,最后我会从准确率、漏诊率等几个方面给你打分”。
这个 21 层的设计不是随便拍脑袋定的,而是像 “搭积木盖房子” 一样,根据 “要解决的问题(识别 X 光片)” 和 “经验规律” 一点点堆出来的。咱们用大白话讲清楚:
目标是让电脑能看懂 X 光片,区分 “正常” 和 “肺炎”。X 光片里有很多细节(比如阴影的形状、边缘),需要一层层处理:
就像医生看片:先看局部细节,再拼出整体印象,最后下结论。层数太少可能 “看不清楚”,太多又 “浪费力气”。
咱们拆成几部分看为什么这么设计:
每个卷积块都是 “Conv2D + 标准化 + 池化 + Dropout” 的组合(4 层),为什么要 4 个这样的块?
一开始用少点 “放大镜”(32 个)找简单特征(比如边缘);
后面用更多 “放大镜”(256 个)找复杂特征(比如阴影的纹理、形状)。
用 4 个块,是因为 X 光片的特征不算特别复杂,但也需要逐步深入 —— 就像剥洋葱,一层一层剥开才能看到核心。
这部分层数少,因为前面的特征已经提取得差不多了,只需要集中做一次判断。
21 层的设计就像 “定制眼镜”:
就像做饭的菜谱,盐放多少、炒多久,是根据食材和口味慢慢试出来的,没有绝对的 “必须”,只有 “合适”。
:这个函数是在给电脑搭建一个 “识别 X 光片的大脑”,专门用来判断片子是 “正常” 还是 “肺炎”。
这个 “大脑” 叫 “卷积神经网络(CNN)”,特别擅长看图片。它的工作方式有点像医生看片:
整个 “大脑” 是一层一层叠起来的,每一层有不同的分工,就像工厂的流水线一样,一步步把图片信息变成 “正常” 或 “肺炎” 的判断。
model = models.Sequential([...]) |
layers.Conv2D(32, (3, 3), activation='relu', input_shape=input_shape), |
layers.BatchNormalization(), |
layers.MaxPooling2D((2, 2)), |
layers.Dropout(0.2), |
后面还有 3 组类似的层:
# 第二组 layers.Conv2D(64, (3, 3), activation='relu'), layers.BatchNormalization(), layers.MaxPooling2D((2, 2)), layers.Dropout(0.3), # ... 还有两组 |
layers.Flatten(), |
layers.Dense(512, activation='relu'), layers.BatchNormalization(), layers.Dropout(0.5), |
layers.Dense(1, activation='sigmoid') |
optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001) model.compile( optimizer=optimizer, loss='binary_crossentropy', metrics=[...]) |
这个函数搭建的 “大脑” 就像一个 “X 光片诊断流水线”:
搭好后,这个 “大脑” 就可以开始学习了 —— 通过看大量标好的 X 光片,慢慢学会区分正常和肺炎。