C-SATS工程副总裁教你如何用TensorFlow分类图像 part2
我们都知道,适当的训练对于将来有效的分类来说至关重要,为了训练工作,我们需要大量准确标记的数据。在第一部分中,我通过下载3000个预先标记的图像跳过了这个挑战。然后我向你展示了在TensorFlow中如何使用带标签的数据训练分类器。在这一部分,我们将使用新的数据集进行训练,并且我将介绍数据可视化工具TensorBoard,以便更好地理解,调试和优化我们的TensorFlow代码。
- 第一部分:http://www.atyun.com/13211_c-sats工程副总裁教你如何用TensorFlow分类图像-part1.html
鉴于我在医疗技术公司C-SATS担任工程副总裁的工作,我希望建立一个与手术有关的分类器。缝合似乎会很不错。它立即投入使用,并且我知道如何识别它。如果机器能够看到缝合正在发生,它可以自动识别缝合手术过程的步骤(或阶段),例如吻合术。并且,因为外科缝线的针和线比较独特,甚至外行也能辨认出来。
我的目标是训练一台识别医学视频中缝合的机器。
我可以访问数十亿帧的手术视频,其中许多包含缝合。但是这样还会面临标记的问题。幸运的是,C-SATS拥有一批经验丰富的注释师,他们是做这件事的专家。我的源数据是JSON中的视频文件和注释。
注释样本如下:
[
{
"annotations": [
{
"endSeconds": 2115.215,
"label": "suturing",
"startSeconds": 2319.541
},
{
"endSeconds": 2976.301,
"label": "suturing",
"startSeconds": 2528.884
}
],
"durationSeconds": 2975,
"videoId": 5
},
{
"annotations": [
// ...etc...
我写了一个Python脚本来使用JSON注释来决定从视频文件中抓取哪些帧。ffmpeg
做实际的抓取。我决定每秒最多抓取一帧,然后我将视频秒的总数除以四,得到10k秒(10k帧)。在找出要抓取的秒数之后,我进行了一个快速测试,看看缝合注释内是否有特定的秒(isWithinSuturingSegment())。下面是grab.py的代码
:
#!/usr/bin/python
# Grab frames from videos with ffmpeg. Use multiple cores.
# Minimum resolution is 1 second--this is a shortcut to get less frames.
# (C)2017 Adam Monsen. License: AGPL v3 or later.
import json
import subprocess
from multiprocessing import Pool
import os
frameList = []
def isWithinSuturingSegment(annotations, timepointSeconds):
for annotation in annotations:
startSeconds = annotation['startSeconds']
endSeconds = annotation['endSeconds']
if timepointSeconds > startSeconds and timepointSeconds < endSeconds:
return True
return False
with open('available-suturing-segments.json') as f:
j = json.load(f)
for video in j:
videoId = video['videoId']
videoDuration = video['durationSeconds']
# generate many ffmpeg frame-grabbing commands
start = 1
stop = videoDuration
step = 4 # Reduce to grab more frames
for timepointSeconds in xrange(start, stop, step):
inputFilename = '/home/adam/Downloads/suturing-videos/{}.mp4'.format
(videoId)
outputFilename = '{}-{}.jpg'.format(video['videoId'],
timepointSeconds)
if isWithinSuturingSegment(video['annotations'], timepointSeconds):
outputFilename = 'suturing/{}'.format(outputFilename)
else:
outputFilename = 'not-suturing/{}'.format(outputFilename)
outputFilename = '/home/adam/local/{}'.format(outputFilename)
commandString = 'ffmpeg -loglevel quiet -ss {} -i {} -frames:v 1 {}'.
format(
timepointSeconds, inputFilename, outputFilename)
frameList.append({
'outputFilename': outputFilename,
'commandString': commandString,
})
def grabFrame(f):
if os.path.isfile(f['outputFilename']):
print 'already completed {}'.format(f['outputFilename'])
else:
print 'processing {}'.format(f['outputFilename'])
subprocess.check_call(f['commandString'].split())
p = Pool(4) # for my 4-core laptop
p.map(grabFrame, frameList)
现在我们像上次那样,再次对这些模型进行再训练。
使用这个脚本来剪出10k帧用了大约10分钟,然后花费一个小时左右,进行再训练识别缝合达到90%的准确性。我使用了训练集之外的新数据进行了抽查,我试过的每一帧都被正确识别(平均置信度分数为88%,中位数置信度分数为91%)。
下面是我的抽查结果。
因图片血腥无法上传可访问网址查看(https://opensource.com/article/17/12/how-to-tensorboard)
如何使用TensorBoard
深度学习与任何其他类型的软件一样,很难可视化内部的原理和交互。幸好我们可以使用TensorBoard。
第一部分的Retrain.py自动生成文件TensorBoard以用于生成表示再训练期间发生了什么的图。
要安装TensorBoard,运行retrain.py后在容器中运行下面代码
。
pip install tensorboard
tensorboard --logdir /tmp/retrain_logs
如果看到下面的输出,就使用浏览器浏览器打开下方网址。
Starting TensorBoard 41 on port 6006
(You can navigate to http://172.17.0.2:6006)
你会看到这样的东西(点击下方视频链接):
- http://imgcdn.atyun.com/2017/12/short-TensorBoard-screencast-1.mp4?_=1
我希望这个视频能够帮到你。在再训练时,我发现在“SCALARS”选项下可以看到,当我们执行更多的训练步骤时或交叉熵减少时准确性如何提高。这就是是我们想要了解的。
- 包学会之浅入浅出Vue.js:开学篇
- 包学会之浅入浅出Vue.js:升学篇
- 一个只有99行代码的JS流程框架 (一)
- 【腾讯云的1001种玩法】试用腾讯云 Windows Server 2012 R2 镜像的几点经验分享
- 一个只有99行代码的JS流程框架(二)
- 看书的时候如何调试书中简单的C+代码?
- gcForest 集成学习方法的 Python 实现
- 云端架构师养成系列之一:高性能云硬盘入门与实战(视频)
- 云端架构师养成系列之二:云端负载均衡上手与实践
- 微信 PaxosStore:海量数据冷热分级架构
- 使用腾讯云容器服务来构建简单web service
- 使用 plotly 绘制数据图表
- 基于云计算的 CV 移动交互应用研究:头部姿态估计综述(2)
- 使用 trie 树实现简单的中文分词
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于maven+ssm的增删改查之maven环境的搭建
- (22)Bash环境变量
- maven之在eclipse中创建maven项目
- wiki百科之将词转换为索引表示
- 【LeetCode】找出数组中重复的数字day01
- pytorch实现的transformer代码分析
- 终于搞懂HashMap的源码了!!!
- (21)Bash用户自定义变量
- python实现支持向量机之具体实现
- Spring boot 集成apollo达到配置的热加载
- ApplicationContext 和beanFactory 和 factoryBean的区别以及联系
- pytorch中的nn.Embedding
- redis的持久化存储AOF的原理
- (三十四)golang--接口
- 回溯法--八皇后问题