与心电心跳分类课题有关的几个核心概念
#临床诊断和病理学方面:
ECG判读在临床心电图工作流程中起着至关重要的作用,各种各样的诊断都被医生们测试,以综合得出一个比较准确的判断,到底病人是得了什么类别的心脏病,或者有几个类别的疾病综合,以便给出后续可靠的治疗或者手术方案。在大数据科学出现以前,医生们主要靠症状,验血,心电图来判断,遇到疑难杂症,即使是有医生专家组会诊,也难以得出准确的结果。
降低误诊率,是大数据科学应用到医学的一个重要课题。以下是一些课题研究重要的思想:
#图像识别:将时间序列的波形转化为图像识别科学,可以简化算法的复杂度。
#卷积神经网络CNN:在过去五年里,算法的实质性进步主要是由一类称为深层神经网络的特定模型推动的。
如果用全连接神经网络处理大尺寸图像具有明显的缺点:首先将图像展开为向量会丢失空间信息;其次参数过多效率低下,训练困难;同时大量的参数也很快会导致网络过拟合。而使用卷积神经网络可以很好地解决上面的问题。
卷积神经网络主要由这几类层构成:输入层、卷积层,ReLU层、池化(Pooling)层和全连接层(全连接层和常规神经网络中的一样)。通过将这些层叠加起来,就可以构建一个完整的卷积神经网络。在实际应用中往往将卷积层与ReLU层共同称之为卷积层,所以卷积层经过卷积操作也是要经过激活函数的。
#残差神经网络:ResNet是由微软研究院的何恺明、张祥雨等人提出的。ResNet 在2015 年的ILSVRC(ImageNet Large Scale Visual Recognition Challenge)中取得了冠军。
残差神经网络的主要贡献是发现了“退化现象(Degradation)”,并针对退化现象发明了 “快捷连接(Shortcut connection)”,极大的消除了深度过大的神经网络训练困难问题。这称得上是深度网络的一个历史大突破。
ResNet的TensorFlow实现
这里给出ResNet50的TensorFlow实现,模型的实现参考了Caffe版本的实现,核心代码如下:
class ResNet50(object):
def init(self, inputs, num_classes=1000, is_training=True,
scope=“resnet50”):
self.inputs =inputs
self.is_training = is_training
self.num_classes = num_classes
with tf.variable_scope(scope):
# construct the model
net = conv2d(inputs, 64, 7, 2, scope="conv1") # -> [batch, 112, 112, 64]
net = tf.nn.relu(batch_norm(net, is_training=self.is_training, scope="bn1"))
net = max_pool(net, 3, 2, scope="maxpool1") # -> [batch, 56, 56, 64]
net = self._block(net, 256, 3, init_stride=1, is_training=self.is_training,
scope="block2") # -> [batch, 56, 56, 256]
net = self._block(net, 512, 4, is_training=self.is_training, scope="block3")
# -> [batch, 28, 28, 512]
net = self._block(net, 1024, 6, is_training=self.is_training, scope="block4")
# -> [batch, 14, 14, 1024]
net = self._block(net, 2048, 3, is_training=self.is_training, scope="block5")
# -> [batch, 7, 7, 2048]
net = avg_pool(net, 7, scope="avgpool5") # -> [batch, 1, 1, 2048]
net = tf.squeeze(net, [1, 2], name="SpatialSqueeze") # -> [batch, 2048]
self.logits = fc(net, self.num_classes, "fc6") # -> [batch, num_classes]
self.predictions = tf.nn.softmax(self.logits)
def _block(self, x, n_out, n, init_stride=2, is_training=True, scope="block"):
with tf.variable_scope(scope):
h_out = n_out // 4
out = self._bottleneck(x, h_out, n_out, stride=init_stride,
is_training=is_training, scope="bottlencek1")
for i in range(1, n):
out = self._bottleneck(out, h_out, n_out, is_training=is_training,
scope=("bottlencek%s" % (i + 1)))
return out
def _bottleneck(self, x, h_out, n_out, stride=None, is_training=True, scope="bottleneck"):
""" A residual bottleneck unit"""
n_in = x.get_shape()[-1]
if stride is None:
stride = 1 if n_in == n_out else 2
with tf.variable_scope(scope):
h = conv2d(x, h_out, 1, stride=stride, scope="conv_1")
h = batch_norm(h, is_training=is_training, scope="bn_1")
h = tf.nn.relu(h)
h = conv2d(h, h_out, 3, stride=1, scope="conv_2")
h = batch_norm(h, is_training=is_training, scope="bn_2")
h = tf.nn.relu(h)
h = conv2d(h, n_out, 1, stride=1, scope="conv_3")
h = batch_norm(h, is_training=is_training, scope="bn_3")
if n_in != n_out:
shortcut = conv2d(x, n_out, 1, stride=stride, scope="conv_4")
shortcut = batch_norm(shortcut, is_training=is_training, scope="bn_4")
else:
shortcut = x
return tf.nn.relu(shortcut + h)