mirror of
https://github.com/LCTT/TranslateProject.git
synced 2026-09-01 04:27:55 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
@@ -1,85 +1,86 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (warmfrog)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10891-1.html)
|
||||
[#]: subject: (Detecting malaria with deep learning)
|
||||
[#]: via: (https://opensource.com/article/19/4/detecting-malaria-deep-learning)
|
||||
[#]: author: (Dipanjan Sarkar https://opensource.com/users/djsarkar)
|
||||
[#]: author: (Dipanjan Sarkar https://opensource.com/users/djsarkar)
|
||||
|
||||
使用深度学习检测疟疾
|
||||
==================
|
||||
人工智能结合开源硬件工具能够提升严重传染病疟疾的诊断。
|
||||
|
||||
> 人工智能结合开源硬件工具能够提升严重传染病疟疾的诊断。
|
||||
|
||||
![][1]
|
||||
|
||||
人工智能(AI)和开源工具,技术,和框架是促进社会进步的强有力的结合。_“健康就是财富”_可能有点陈词滥调,但它却是非常准确的!在本篇文章,我们将测试 AI 是如何与低花费,有效,精确的开源深度学习方法一起被利用来检测致死的传染病疟疾。
|
||||
人工智能(AI)和开源工具、技术和框架是促进社会进步的强有力的结合。“健康就是财富”可能有点陈词滥调,但它却是非常准确的!在本篇文章,我们将测试 AI 是如何与低成本、有效、精确的开源深度学习方法结合起来一起用来检测致死的传染病疟疾。
|
||||
|
||||
我既不是一个医生,也不是一个医疗保健研究者,我也绝不像他们那样合格,我只是对将 AI 应用到医疗保健研究感兴趣。在这片文章中我的想法是展示 AI 和开源解决方案如何帮助疟疾检测和减少人工劳动的方法。
|
||||
|
||||
![Python and TensorFlow][2]
|
||||
|
||||
Python and TensorFlow: 一个构建开源深度学习方法的很棒的结合
|
||||
*Python 和 TensorFlow: 一个构建开源深度学习方法的很棒的结合*
|
||||
|
||||
感谢 Python 的强大 和像 TensorFlow 这样的深度学习框架,我们能够构建鲁棒的,大规模的,有效的深度学习方法。因为这些工具是自由和开源的,我们能够构建低成本的能够轻易被任何人采纳和使用的解决方案。让我们开始吧!
|
||||
感谢 Python 的强大和像 TensorFlow 这样的深度学习框架,我们能够构建健壮的、大规模的、有效的深度学习方法。因为这些工具是自由和开源的,我们能够构建非常经济且易于被任何人采纳和使用的解决方案。让我们开始吧!
|
||||
|
||||
### 项目动机
|
||||
|
||||
疟疾是由_疟原虫_造成的致死的,有传染性的,蚊子传播的疾病,主要通过受感染的雌性按蚊叮咬传播。共有五种寄生虫能够造成疟疾,但是样例中的大多数是这两种类型- _恶性疟原虫_ 和 _间日疟原虫_ 造成的。
|
||||
疟疾是由*疟原虫*造成的致死的、有传染性的、蚊子传播的疾病,主要通过受感染的雌性按蚊叮咬传播。共有五种寄生虫能够引起疟疾,但是大多数病例是这两种类型造成的:恶性疟原虫和间日疟原虫。
|
||||
|
||||
![疟疾热图][3]
|
||||
|
||||
这个地图显示了疟疾在全球传播分布形势,尤其在热带地区,但疾病的性质和致命性是该项目的主要动机。
|
||||
|
||||
如果一个雌性蚊子咬了你,蚊子携带的寄生虫进入你的血液并且开始破坏携带氧气的红细胞(RBC)。通常,疟疾的最初症状类似于流感病毒,在蚊子叮咬后,他们通常在几天或几周内发作。然而,这些致死的寄生虫可以在你的身体里生存长达一年并且不会造成任何症状,延迟治疗可能造成并发症甚至死亡。因此,早期的检查能够挽救生命。
|
||||
如果一只受感染雌性蚊子叮咬了你,蚊子携带的寄生虫进入你的血液,并且开始破坏携带氧气的红细胞(RBC)。通常,疟疾的最初症状类似于流感病毒,在蚊子叮咬后,他们通常在几天或几周内发作。然而,这些致死的寄生虫可以在你的身体里生存长达一年并且不会造成任何症状,延迟治疗可能造成并发症甚至死亡。因此,早期的检查能够挽救生命。
|
||||
|
||||
世界健康组织(WHO)的[疟疾事件][4]暗示世界近乎一半的人口面临疟疾的风险,有超过 2 亿 的疟疾病例,每年由于疟疾造成的死亡近乎 40 万。这是使疟疾检测和诊断快速,简单和有效的一个动机。
|
||||
世界健康组织(WHO)的[疟疾实情][4]表明,世界近乎一半的人口面临疟疾的风险,有超过 2 亿的疟疾病例,每年由于疟疾造成的死亡将近 40 万。这是使疟疾检测和诊断快速、简单和有效的一个动机。
|
||||
|
||||
### 检测疟疾的方法
|
||||
|
||||
有几种方法能够用来检测和诊断疟疾。该文中的项目就是基于 Rajaraman,et al. 的论文:“[预先训练的卷积神经网络作为特征提取器,用于改善薄血涂片图像中的疟疾寄生虫检测][5]”,介绍了一些方法,包含聚合酶链反应(PCR)和快速诊断测试(RDT)。这两种测试通常在高质量的显微镜下使用,但这样的设备不是轻易能够获得的。
|
||||
有几种方法能够用来检测和诊断疟疾。该文中的项目就是基于 Rajaraman, et al. 的论文:“[预先训练的卷积神经网络作为特征提取器,用于改善薄血涂片图像中的疟疾寄生虫检测][5]”介绍的一些方法,包含聚合酶链反应(PCR)和快速诊断测试(RDT)。这两种测试通常用于无法提供高质量显微镜服务的地方。
|
||||
|
||||
标准的疟疾诊断通常使基于血液涂片工作流的,根据 Carlos Ariza 的文章“[Malaria Hero: 一个更快诊断疟原虫的网络应用][6]”,我从中了解到 Adrian Rosebrock 的“[使用 Keras 的深度学习和医学图像分析][7]”。我感激这些优秀的资源的作者,让我在疟原虫预防,诊断和治疗方面有了更多的想法。
|
||||
标准的疟疾诊断通常是基于血液涂片工作流程的,根据 Carlos Ariza 的文章“[Malaria Hero:一个更快诊断疟原虫的网络应用][6]”,我从中了解到 Adrian Rosebrock 的“[使用 Keras 的深度学习和医学图像分析][7]”。我感激这些优秀的资源的作者,让我在疟原虫预防、诊断和治疗方面有了更多的想法。
|
||||
|
||||
![疟原虫检测的血涂片工作流程][8]
|
||||
|
||||
一个疟原虫检测的血涂片工作流程
|
||||
*一个疟原虫检测的血涂片工作流程*
|
||||
|
||||
根据 WHO 草案,诊断通常包括对放大 100 倍的血涂片的集中检测。训练人们人工计数在 5000 个细胞中有多少红细胞中包含疟原虫。正如上述解释中引用的 Rajaraman, et al. 的论文:
|
||||
根据 WHO 方案,诊断通常包括对放大 100 倍的血涂片的集中检测。受过训练的人们手工计算在 5000 个细胞中有多少红细胞中包含疟原虫。正如上述解释中引用的 Rajaraman, et al. 的论文:
|
||||
|
||||
> 薄血涂片帮助检测疟原虫的存在性并且帮助识别造成传染(疾病控制和抑制中心,2012)的物种。诊断准确性在很大程度上取决于人类的专业知识,并且可能受到观察者间差异和疾病流行/资源受限区域大规模诊断所造成的不利影响(Mitiku, Mengistu, and Gelaw, 2003)。可替代的技术是使用聚合酶链反应(PCR)和快速诊断测试(RDT);然而,PCR 分析受限于它的性能(Hommelsheim, et al., 2014),RDT 在疾病流行的地区成本效益低(Hawkes,Katsuva, and Masumbuko, 2009)。
|
||||
> 厚血涂片有助于检测寄生虫的存在,而薄血涂片有助于识别引起感染的寄生虫种类(疾病控制和预防中心, 2012)。诊断准确性在很大程度上取决于诊断人的专业知识,并且可能受到观察者间差异和疾病流行/资源受限区域大规模诊断所造成的不利影响(Mitiku, Mengistu 和 Gelaw, 2003)。可替代的技术是使用聚合酶链反应(PCR)和快速诊断测试(RDT);然而,PCR 分析受限于它的性能(Hommelsheim, et al., 2014),RDT 在疾病流行的地区成本效益低(Hawkes, Katsuva 和 Masumbuko, 2009)。
|
||||
|
||||
因此,疟疾检测可能受益于使用机器学习的自动化。
|
||||
|
||||
### 疟原虫检测的深度学习
|
||||
### 疟疾检测的深度学习
|
||||
|
||||
人工诊断血涂片是一个加强的人工过程,需要专业知识来分类和计数被寄生虫感染的和未感染的细胞。这个过程可能不能很好的规模化,尤其在那些专业人士不足的地区。在利用最先进的图像处理和分析技术提取人工选取特征和构建基于机器学习的分类模型方面取得了一些进展。然而,这些模型不能大规模推广,因为没有更多的数据用来训练,并且人工选取特征需要花费很长时间。
|
||||
人工诊断血涂片是一个繁重的手工过程,需要专业知识来分类和计数被寄生虫感染的和未感染的细胞。这个过程可能不能很好的规模化,尤其在那些专业人士不足的地区。在利用最先进的图像处理和分析技术提取人工选取特征和构建基于机器学习的分类模型方面取得了一些进展。然而,这些模型不能大规模推广,因为没有更多的数据用来训练,并且人工选取特征需要花费很长时间。
|
||||
|
||||
深度学习模型,或者更具体地讲,卷积神经网络(CNNs),已经被证明在各种计算机视觉任务中非常有效。(如果你想有额外的关于 CNNs 的背景知识,我推荐你阅读[视觉识别的 CS2331n 卷积神经网络][9]。)简单地讲,CNN 模型的关键层包含卷积和池化层,正如下面图像显示。
|
||||
深度学习模型,或者更具体地讲,卷积神经网络(CNN),已经被证明在各种计算机视觉任务中非常有效。(如果你想更多的了解关于 CNN 的背景知识,我推荐你阅读[视觉识别的 CS2331n 卷积神经网络][9]。)简单地讲,CNN 模型的关键层包含卷积和池化层,正如下图所示。
|
||||
|
||||
![A typical CNN architecture][10]
|
||||
|
||||
一个典型的 CNN 架构
|
||||
*一个典型的 CNN 架构*
|
||||
|
||||
卷积层从数据中学习空间层级模式,它是平移不变的,因此它们能够学习不同方面的图像。例如,第一个卷积层将学习小的和本地图案,例如边缘和角落,第二个卷积层学习基于第一层的特征的更大的图案,等等。这允许 CNNs 自动化提取特征并且学习对于新数据点通用的有效的特征。池化层帮助下采样和降维。
|
||||
卷积层从数据中学习空间层级模式,它是平移不变的,因此它们能够学习图像的不同方面。例如,第一个卷积层将学习小的和局部图案,例如边缘和角落,第二个卷积层将基于第一层的特征学习更大的图案,等等。这允许 CNN 自动化提取特征并且学习对于新数据点通用的有效的特征。池化层有助于下采样和减少尺寸。
|
||||
|
||||
因此,CNNs 帮助自动化和规模化的特征工程。同样,在模型末尾加上密集层允许我们执行像图像分类这样的任务。使用像 CNNs 者的深度学习模型自动的疟疾检测可能非常有效,便宜和具有规模性,尤其是迁移学习和预训练模型效果非常好,甚至在少量数据的约束下。
|
||||
因此,CNN 有助于自动化和规模化的特征工程。同样,在模型末尾加上密集层允许我们执行像图像分类这样的任务。使用像 CNN 这样的深度学习模型自动的疟疾检测可能非常有效、便宜和具有规模性,尤其是迁移学习和预训练模型效果非常好,甚至在少量数据的约束下。
|
||||
|
||||
Rajaraman, et al. 的论文在一个数据集上利用六个预训练模型在检测疟疾 vs 无感染样本获取到令人吃惊的 95.9% 的准确率。我们的关注点是从头开始尝试一些简单的 CNN 模型和用一个预训练的训练模型使用迁移学习来查看我们能够从相同的数据集中得到什么。我们将使用开源工具和框架,包括 Python 和 TensorFlow,来构建我们的模型。
|
||||
Rajaraman, et al. 的论文在一个数据集上利用六个预训练模型在检测疟疾对比无感染样本获取到令人吃惊的 95.9% 的准确率。我们的重点是从头开始尝试一些简单的 CNN 模型和用一个预训练的训练模型使用迁移学习来查看我们能够从相同的数据集中得到什么。我们将使用开源工具和框架,包括 Python 和 TensorFlow,来构建我们的模型。
|
||||
|
||||
### 数据集
|
||||
|
||||
我们分析的数据来自 Lister Hill 国家生物医学交流中心(LHNCBC),国家医学图书馆(NLM)的一部分,他们细心收集和标记了健康和受感染的血涂片图像的[公众可获得的数据集][11]。这些研究者已经开发了一个运行在 Android 智能手机的移动[疟疾检测应用][12],连接到一个传统的光学显微镜。它们使用 吉姆萨染液 将 150 个受恶性疟原虫感染的和 50 个健康病人的薄血涂片染色,这些薄血涂片是在孟加拉的吉大港医学院附属医院收集和照相的。使用智能手机的内置相机获取每个显微镜视窗内的图像。这些图片由在泰国曼谷的马希多-牛津热带医学研究所的一个专家使用幻灯片阅读器标记的。
|
||||
我们分析的数据来自 Lister Hill 国家生物医学交流中心(LHNCBC)的研究人员,该中心是国家医学图书馆(NLM)的一部分,他们细心收集和标记了公开可用的健康和受感染的血涂片图像的[数据集][11]。这些研究者已经开发了一个运行在 Android 智能手机的[疟疾检测手机应用][12],连接到一个传统的光学显微镜。它们使用吉姆萨染液将 150 个受恶性疟原虫感染的和 50 个健康病人的薄血涂片染色,这些薄血涂片是在孟加拉的吉大港医学院附属医院收集和照相的。使用智能手机的内置相机获取每个显微镜视窗内的图像。这些图片由在泰国曼谷的马希多-牛津热带医学研究所的一个专家使用幻灯片阅读器标记的。
|
||||
|
||||
让我们简洁的查看数据集的结构。首先,我将安装一些基础的依赖(基于使用的操作系统)。
|
||||
让我们简要地查看一下数据集的结构。首先,我将安装一些基础的依赖(基于使用的操作系统)。
|
||||
|
||||
![Installing dependencies][13]
|
||||
|
||||
我使用的是云上的带有一个 GPU 的基于 Debian 的操作系统,这样我能更快的运行我的模型。为了查看目录结构,我们必须安装 tree 依赖(如果我们没有安装的话)使用 **sudo apt install tree**。
|
||||
我使用的是云上的带有一个 GPU 的基于 Debian 的操作系统,这样我能更快的运行我的模型。为了查看目录结构,我们必须使用 `sudo apt install tree` 安装 `tree` 及其依赖(如果我们没有安装的话)。
|
||||
|
||||
![Installing the tree dependency][14]
|
||||
|
||||
我们有两个文件夹包含血细胞的图像,包括受感染的和健康的。我们可以获取关于图像总数更多的细节通过输入:
|
||||
|
||||
我们有两个文件夹包含血细胞的图像,包括受感染的和健康的。我们通过输入可以获取关于图像总数更多的细节:
|
||||
|
||||
```
|
||||
import os
|
||||
@@ -97,7 +98,7 @@ len(infected_files), len(healthy_files)
|
||||
(13779, 13779)
|
||||
```
|
||||
|
||||
看起来我们有一个平衡的 13,779 张疟疾的 和 13,779 张非疟疾的(健康的)血细胞图像。让我们根据这些构建数据帧,我们将用这些数据帧来构建我们的数据集。
|
||||
看起来我们有一个平衡的数据集,包含 13,779 张疟疾的和 13,779 张非疟疾的(健康的)血细胞图像。让我们根据这些构建数据帧,我们将用这些数据帧来构建我们的数据集。
|
||||
|
||||
|
||||
```
|
||||
@@ -107,8 +108,8 @@ import pandas as pd
|
||||
np.random.seed(42)
|
||||
|
||||
files_df = pd.DataFrame({
|
||||
'filename': infected_files + healthy_files,
|
||||
'label': ['malaria'] * len(infected_files) + ['healthy'] * len(healthy_files)
|
||||
'filename': infected_files + healthy_files,
|
||||
'label': ['malaria'] * len(infected_files) + ['healthy'] * len(healthy_files)
|
||||
}).sample(frac=1, random_state=42).reset_index(drop=True)
|
||||
|
||||
files_df.head()
|
||||
@@ -116,9 +117,9 @@ files_df.head()
|
||||
|
||||
![Datasets][15]
|
||||
|
||||
### 构建和参所图像数据集
|
||||
### 构建和了解图像数据集
|
||||
|
||||
为了构建深度学习模型,我们需要训练数据,但是我们还需要使用不可见的数据测试模型的性能。相应的,我们将使用 60:10:30 的划分用于训练,验证和测试数据集。我们将在训练期间应用训练和验证数据集并用测试数据集来检查模型的性能。
|
||||
为了构建深度学习模型,我们需要训练数据,但是我们还需要使用不可见的数据测试模型的性能。相应的,我们将使用 60:10:30 的比例来划分用于训练、验证和测试的数据集。我们将在训练期间应用训练和验证数据集,并用测试数据集来检查模型的性能。
|
||||
|
||||
|
||||
```
|
||||
@@ -126,24 +127,23 @@ from sklearn.model_selection import train_test_split
|
||||
from collections import Counter
|
||||
|
||||
train_files, test_files, train_labels, test_labels = train_test_split(files_df['filename'].values,
|
||||
files_df['label'].values,
|
||||
test_size=0.3, random_state=42)
|
||||
files_df['label'].values,
|
||||
test_size=0.3, random_state=42)
|
||||
train_files, val_files, train_labels, val_labels = train_test_split(train_files,
|
||||
train_labels,
|
||||
test_size=0.1, random_state=42)
|
||||
train_labels,
|
||||
test_size=0.1, random_state=42)
|
||||
|
||||
print(train_files.shape, val_files.shape, test_files.shape)
|
||||
print('Train:', Counter(train_labels), '\nVal:', Counter(val_labels), '\nTest:', Counter(test_labels))
|
||||
|
||||
# Output
|
||||
(17361,) (1929,) (8268,)
|
||||
Train: Counter({'healthy': 8734, 'malaria': 8627})
|
||||
Val: Counter({'healthy': 970, 'malaria': 959})
|
||||
Train: Counter({'healthy': 8734, 'malaria': 8627})
|
||||
Val: Counter({'healthy': 970, 'malaria': 959})
|
||||
Test: Counter({'malaria': 4193, 'healthy': 4075})
|
||||
```
|
||||
|
||||
这些图片维度并不相同,因此血涂片和细胞图像是基于人类,测试方法,图片的朝向。让我们总结我们的训练数据集的统计信息来决定最佳的图像维度(牢记,我们根本不会碰测试数据集)。
|
||||
|
||||
这些图片尺寸并不相同,因为血涂片和细胞图像是基于人、测试方法、图片方向不同而不同的。让我们总结我们的训练数据集的统计信息来决定最佳的图像尺寸(牢记,我们根本不会碰测试数据集)。
|
||||
|
||||
```
|
||||
import cv2
|
||||
@@ -151,24 +151,25 @@ from concurrent import futures
|
||||
import threading
|
||||
|
||||
def get_img_shape_parallel(idx, img, total_imgs):
|
||||
if idx % 5000 == 0 or idx == (total_imgs - 1):
|
||||
print('{}: working on img num: {}'.format(threading.current_thread().name,
|
||||
idx))
|
||||
return cv2.imread(img).shape
|
||||
|
||||
if idx % 5000 == 0 or idx == (total_imgs - 1):
|
||||
print('{}: working on img num: {}'.format(threading.current_thread().name,
|
||||
idx))
|
||||
return cv2.imread(img).shape
|
||||
|
||||
ex = futures.ThreadPoolExecutor(max_workers=None)
|
||||
data_inp = [(idx, img, len(train_files)) for idx, img in enumerate(train_files)]
|
||||
print('Starting Img shape computation:')
|
||||
train_img_dims_map = ex.map(get_img_shape_parallel,
|
||||
[record[0] for record in data_inp],
|
||||
[record[1] for record in data_inp],
|
||||
[record[2] for record in data_inp])
|
||||
train_img_dims_map = ex.map(get_img_shape_parallel,
|
||||
[record[0] for record in data_inp],
|
||||
[record[1] for record in data_inp],
|
||||
[record[2] for record in data_inp])
|
||||
train_img_dims = list(train_img_dims_map)
|
||||
print('Min Dimensions:', np.min(train_img_dims, axis=0))
|
||||
print('Min Dimensions:', np.min(train_img_dims, axis=0))
|
||||
print('Avg Dimensions:', np.mean(train_img_dims, axis=0))
|
||||
print('Median Dimensions:', np.median(train_img_dims, axis=0))
|
||||
print('Max Dimensions:', np.max(train_img_dims, axis=0))
|
||||
|
||||
|
||||
# Output
|
||||
Starting Img shape computation:
|
||||
ThreadPoolExecutor-0_0: working on img num: 0
|
||||
@@ -176,27 +177,26 @@ ThreadPoolExecutor-0_17: working on img num: 5000
|
||||
ThreadPoolExecutor-0_15: working on img num: 10000
|
||||
ThreadPoolExecutor-0_1: working on img num: 15000
|
||||
ThreadPoolExecutor-0_7: working on img num: 17360
|
||||
Min Dimensions: [46 46 3]
|
||||
Avg Dimensions: [132.77311215 132.45757733 3.]
|
||||
Median Dimensions: [130. 130. 3.]
|
||||
Max Dimensions: [385 394 3]
|
||||
Min Dimensions: [46 46 3]
|
||||
Avg Dimensions: [132.77311215 132.45757733 3.]
|
||||
Median Dimensions: [130. 130. 3.]
|
||||
Max Dimensions: [385 394 3]
|
||||
```
|
||||
|
||||
我们应用并行处理来加速图像读取,并且在总结统计时,我们将重新调整每幅图片到 125x125 像素。让我们载入我们所有的图像并重新调整它们为这些固定的大小。
|
||||
|
||||
我们应用并行处理来加速图像读取,并且基于汇总统计结果,我们将每幅图片的尺寸重新调整到 125x125 像素。让我们载入我们所有的图像并重新调整它们为这些固定尺寸。
|
||||
|
||||
```
|
||||
IMG_DIMS = (125, 125)
|
||||
|
||||
def get_img_data_parallel(idx, img, total_imgs):
|
||||
if idx % 5000 == 0 or idx == (total_imgs - 1):
|
||||
print('{}: working on img num: {}'.format(threading.current_thread().name,
|
||||
idx))
|
||||
img = cv2.imread(img)
|
||||
img = cv2.resize(img, dsize=IMG_DIMS,
|
||||
interpolation=cv2.INTER_CUBIC)
|
||||
img = np.array(img, dtype=np.float32)
|
||||
return img
|
||||
if idx % 5000 == 0 or idx == (total_imgs - 1):
|
||||
print('{}: working on img num: {}'.format(threading.current_thread().name,
|
||||
idx))
|
||||
img = cv2.imread(img)
|
||||
img = cv2.resize(img, dsize=IMG_DIMS,
|
||||
interpolation=cv2.INTER_CUBIC)
|
||||
img = np.array(img, dtype=np.float32)
|
||||
return img
|
||||
|
||||
ex = futures.ThreadPoolExecutor(max_workers=None)
|
||||
train_data_inp = [(idx, img, len(train_files)) for idx, img in enumerate(train_files)]
|
||||
@@ -204,27 +204,28 @@ val_data_inp = [(idx, img, len(val_files)) for idx, img in enumerate(val_files)]
|
||||
test_data_inp = [(idx, img, len(test_files)) for idx, img in enumerate(test_files)]
|
||||
|
||||
print('Loading Train Images:')
|
||||
train_data_map = ex.map(get_img_data_parallel,
|
||||
[record[0] for record in train_data_inp],
|
||||
[record[1] for record in train_data_inp],
|
||||
[record[2] for record in train_data_inp])
|
||||
train_data_map = ex.map(get_img_data_parallel,
|
||||
[record[0] for record in train_data_inp],
|
||||
[record[1] for record in train_data_inp],
|
||||
[record[2] for record in train_data_inp])
|
||||
train_data = np.array(list(train_data_map))
|
||||
|
||||
print('\nLoading Validation Images:')
|
||||
val_data_map = ex.map(get_img_data_parallel,
|
||||
[record[0] for record in val_data_inp],
|
||||
[record[1] for record in val_data_inp],
|
||||
[record[2] for record in val_data_inp])
|
||||
val_data_map = ex.map(get_img_data_parallel,
|
||||
[record[0] for record in val_data_inp],
|
||||
[record[1] for record in val_data_inp],
|
||||
[record[2] for record in val_data_inp])
|
||||
val_data = np.array(list(val_data_map))
|
||||
|
||||
print('\nLoading Test Images:')
|
||||
test_data_map = ex.map(get_img_data_parallel,
|
||||
[record[0] for record in test_data_inp],
|
||||
[record[1] for record in test_data_inp],
|
||||
[record[2] for record in test_data_inp])
|
||||
test_data_map = ex.map(get_img_data_parallel,
|
||||
[record[0] for record in test_data_inp],
|
||||
[record[1] for record in test_data_inp],
|
||||
[record[2] for record in test_data_inp])
|
||||
test_data = np.array(list(test_data_map))
|
||||
|
||||
train_data.shape, val_data.shape, test_data.shape
|
||||
train_data.shape, val_data.shape, test_data.shape
|
||||
|
||||
|
||||
# Output
|
||||
Loading Train Images:
|
||||
@@ -245,23 +246,22 @@ ThreadPoolExecutor-1_8: working on img num: 8267
|
||||
((17361, 125, 125, 3), (1929, 125, 125, 3), (8268, 125, 125, 3))
|
||||
```
|
||||
|
||||
我们再次应用并行处理来加速有关图像载入和重新调整大小。最终,我们获得了想要的维度的图片张量,正如之前描述的。我们现在查看一些血细胞图像样本来对我们的数据什么样有个印象。
|
||||
|
||||
我们再次应用并行处理来加速有关图像载入和重新调整大小的计算。最终,我们获得了所需尺寸的图片张量,正如前面的输出所示。我们现在查看一些血细胞图像样本,以对我们的数据有个印象。
|
||||
|
||||
```
|
||||
import matplotlib.pyplot as plt
|
||||
%matplotlib inline
|
||||
|
||||
plt.figure(1 , figsize = (8 , 8))
|
||||
n = 0
|
||||
n = 0
|
||||
for i in range(16):
|
||||
n += 1
|
||||
r = np.random.randint(0 , train_data.shape[0] , 1)
|
||||
plt.subplot(4 , 4 , n)
|
||||
plt.subplots_adjust(hspace = 0.5 , wspace = 0.5)
|
||||
plt.imshow(train_data[r[0]]/255.)
|
||||
plt.title('{}'.format(train_labels[r[0]]))
|
||||
plt.xticks([]) , plt.yticks([])
|
||||
n += 1
|
||||
r = np.random.randint(0 , train_data.shape[0] , 1)
|
||||
plt.subplot(4 , 4 , n)
|
||||
plt.subplots_adjust(hspace = 0.5 , wspace = 0.5)
|
||||
plt.imshow(train_data[r[0]]/255.)
|
||||
plt.title('{}'.format(train_labels[r[0]]))
|
||||
plt.xticks([]) , plt.yticks([])
|
||||
```
|
||||
|
||||
![Malaria cell samples][16]
|
||||
@@ -270,7 +270,6 @@ plt.xticks([]) , plt.yticks([])
|
||||
|
||||
开始我们的模型训练前,我们必须建立一些基础的配置设置。
|
||||
|
||||
|
||||
```
|
||||
BATCH_SIZE = 64
|
||||
NUM_CLASSES = 2
|
||||
@@ -290,12 +289,12 @@ val_labels_enc = le.transform(val_labels)
|
||||
|
||||
print(train_labels[:6], train_labels_enc[:6])
|
||||
|
||||
|
||||
# Output
|
||||
['malaria' 'malaria' 'malaria' 'healthy' 'healthy' 'malaria'] [1 1 1 0 0 1]
|
||||
```
|
||||
|
||||
我们修复我们的图像维度,批大小,和历元并编码我们的分类类标签。TensorFlow 2.0 于 2019 年三月发布,这个练习是非常好的借口来试用它。
|
||||
|
||||
我们修复我们的图像尺寸、批量大小,和纪元,并编码我们的分类的类标签。TensorFlow 2.0 于 2019 年三月发布,这个练习是尝试它的完美理由。
|
||||
|
||||
```
|
||||
import tensorflow as tf
|
||||
@@ -312,24 +311,23 @@ tf.__version__
|
||||
|
||||
### 深度学习训练
|
||||
|
||||
在模型训练阶段,我们将构建三个深度训练模型,使用我们的训练集训练,使用验证数据比较它们的性能。我们然后保存这些模型并在之后的模型评估阶段使用它们。
|
||||
在模型训练阶段,我们将构建三个深度训练模型,使用我们的训练集训练,使用验证数据比较它们的性能。然后,我们保存这些模型并在之后的模型评估阶段使用它们。
|
||||
|
||||
#### 模型 1:从头开始的 CNN
|
||||
|
||||
我们的第一个疟疾检测模型将从头开始构建和训练一个基础的 CNN。首先,让我们定义我们的模型架构,
|
||||
|
||||
|
||||
```
|
||||
inp = tf.keras.layers.Input(shape=INPUT_SHAPE)
|
||||
|
||||
conv1 = tf.keras.layers.Conv2D(32, kernel_size=(3, 3),
|
||||
activation='relu', padding='same')(inp)
|
||||
conv1 = tf.keras.layers.Conv2D(32, kernel_size=(3, 3),
|
||||
activation='relu', padding='same')(inp)
|
||||
pool1 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv1)
|
||||
conv2 = tf.keras.layers.Conv2D(64, kernel_size=(3, 3),
|
||||
activation='relu', padding='same')(pool1)
|
||||
conv2 = tf.keras.layers.Conv2D(64, kernel_size=(3, 3),
|
||||
activation='relu', padding='same')(pool1)
|
||||
pool2 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv2)
|
||||
conv3 = tf.keras.layers.Conv2D(128, kernel_size=(3, 3),
|
||||
activation='relu', padding='same')(pool2)
|
||||
conv3 = tf.keras.layers.Conv2D(128, kernel_size=(3, 3),
|
||||
activation='relu', padding='same')(pool2)
|
||||
pool3 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv3)
|
||||
|
||||
flat = tf.keras.layers.Flatten()(pool3)
|
||||
@@ -343,31 +341,32 @@ out = tf.keras.layers.Dense(1, activation='sigmoid')(drop2)
|
||||
|
||||
model = tf.keras.Model(inputs=inp, outputs=out)
|
||||
model.compile(optimizer='adam',
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy'])
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy'])
|
||||
model.summary()
|
||||
|
||||
|
||||
# Output
|
||||
Model: "model"
|
||||
_________________________________________________________________
|
||||
Layer (type) Output Shape Param #
|
||||
Layer (type) Output Shape Param #
|
||||
=================================================================
|
||||
input_1 (InputLayer) [(None, 125, 125, 3)] 0
|
||||
input_1 (InputLayer) [(None, 125, 125, 3)] 0
|
||||
_________________________________________________________________
|
||||
conv2d (Conv2D) (None, 125, 125, 32) 896
|
||||
conv2d (Conv2D) (None, 125, 125, 32) 896
|
||||
_________________________________________________________________
|
||||
max_pooling2d (MaxPooling2D) (None, 62, 62, 32) 0
|
||||
max_pooling2d (MaxPooling2D) (None, 62, 62, 32) 0
|
||||
_________________________________________________________________
|
||||
conv2d_1 (Conv2D) (None, 62, 62, 64) 18496
|
||||
conv2d_1 (Conv2D) (None, 62, 62, 64) 18496
|
||||
_________________________________________________________________
|
||||
...
|
||||
...
|
||||
_________________________________________________________________
|
||||
dense_1 (Dense) (None, 512) 262656
|
||||
dense_1 (Dense) (None, 512) 262656
|
||||
_________________________________________________________________
|
||||
dropout_1 (Dropout) (None, 512) 0
|
||||
dropout_1 (Dropout) (None, 512) 0
|
||||
_________________________________________________________________
|
||||
dense_2 (Dense) (None, 1) 513
|
||||
dense_2 (Dense) (None, 1) 513
|
||||
=================================================================
|
||||
Total params: 15,102,529
|
||||
Trainable params: 15,102,529
|
||||
@@ -375,26 +374,26 @@ Non-trainable params: 0
|
||||
_________________________________________________________________
|
||||
```
|
||||
|
||||
基于这些代码的架构,我们的 CNN 模型有三个卷积和一个池化层,跟随两个致密层,以及用于正则化的丢失。让我们训练我们的模型。
|
||||
基于这些代码的架构,我们的 CNN 模型有三个卷积和一个池化层,其后是两个致密层,以及用于正则化的失活。让我们训练我们的模型。
|
||||
|
||||
|
||||
```
|
||||
import datetime
|
||||
|
||||
logdir = os.path.join('/home/dipanzan_sarkar/projects/tensorboard_logs',
|
||||
datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
|
||||
logdir = os.path.join('/home/dipanzan_sarkar/projects/tensorboard_logs',
|
||||
datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
|
||||
tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
|
||||
reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5,
|
||||
patience=2, min_lr=0.000001)
|
||||
patience=2, min_lr=0.000001)
|
||||
callbacks = [reduce_lr, tensorboard_callback]
|
||||
|
||||
history = model.fit(x=train_imgs_scaled, y=train_labels_enc,
|
||||
batch_size=BATCH_SIZE,
|
||||
epochs=EPOCHS,
|
||||
validation_data=(val_imgs_scaled, val_labels_enc),
|
||||
callbacks=callbacks,
|
||||
verbose=1)
|
||||
|
||||
history = model.fit(x=train_imgs_scaled, y=train_labels_enc,
|
||||
batch_size=BATCH_SIZE,
|
||||
epochs=EPOCHS,
|
||||
validation_data=(val_imgs_scaled, val_labels_enc),
|
||||
callbacks=callbacks,
|
||||
verbose=1)
|
||||
|
||||
|
||||
# Output
|
||||
Train on 17361 samples, validate on 1929 samples
|
||||
@@ -439,57 +438,53 @@ l2 = ax2.legend(loc="best")
|
||||
|
||||
![Learning curves for basic CNN][17]
|
||||
|
||||
基础 CNN 学习曲线
|
||||
|
||||
我们可以看在在第五个历元,情况并没有改善很多。让我们保存这个模型用于将来的评估。
|
||||
*基础 CNN 学习曲线*
|
||||
|
||||
我们可以看在在第五个纪元,情况并没有改善很多。让我们保存这个模型用于将来的评估。
|
||||
|
||||
```
|
||||
`model.save('basic_cnn.h5')`
|
||||
model.save('basic_cnn.h5')
|
||||
```
|
||||
|
||||
#### 深度迁移学习
|
||||
|
||||
就像人类有与生俱来的能力在不同任务间传输知识,迁移学习允许我们利用从以前任务学到的知识用到新的任务,相关的任务,甚至在机器学习或深度学习的上下文中。如果想深入探究迁移学习,你应该看我的文章“[一个易于理解与现实应用一起学习深度学习中的迁移学习的指导实践][18]”和我的书[ Python 迁移学习实践][19]。
|
||||
就像人类有与生俱来在不同任务间传输知识的能力一样,迁移学习允许我们利用从以前任务学到的知识用到新的相关的任务,即使在机器学习或深度学习的情况下也是如此。如果想深入探究迁移学习,你应该看我的文章“[一个易于理解与现实应用一起学习深度学习中的迁移学习的指导实践][18]”和我的书《[Python 迁移学习实践][19]》。
|
||||
|
||||
![深度迁移学习的想法][20]
|
||||
|
||||
在这篇实践中我们想要探索的想法是:
|
||||
|
||||
> 在我们的问题上下文中,我们能够利用一个预训练深度学习模型(在大数据集上训练的,像 ImageNet)通过应用和迁移知识来解决疟疾检测的问题吗?
|
||||
> 在我们的问题背景下,我们能够利用一个预训练深度学习模型(在大数据集上训练的,像 ImageNet)通过应用和迁移知识来解决疟疾检测的问题吗?
|
||||
|
||||
我们将应用两个深度迁移学习的最流行的策略。
|
||||
我们将应用两个最流行的深度迁移学习策略。
|
||||
|
||||
* 预训练模型作为特征提取器
|
||||
* 微调的预训练模型
|
||||
|
||||
|
||||
|
||||
我们将使用预训练的 VGG-19 深度训练模型,由剑桥大学的视觉几何组(VGG)开发,作为我们的实验。一个像 VGG-19 的预训练模型在一个大的数据集上使用了很多不同的图像分类训练([Imagenet][21])。因此,这个模型应该已经学习到了鲁棒的特征层级结构,相对于你的 CNN 模型学到的特征,是空间不变的,转动不变的,平移不变的。因此,这个模型,已经从百万幅图片中学习到了一个好的特征显示,对于像疟疾检测这样的计算机视觉问题,可以作为一个好的合适新图像的特征提取器。在我们的问题中释放迁移学习的能力之前,让我们先讨论 VGG-19 模型。
|
||||
我们将使用预训练的 VGG-19 深度训练模型(由剑桥大学的视觉几何组(VGG)开发)进行我们的实验。像 VGG-19 这样的预训练模型是在一个大的数据集([Imagenet][21])上使用了很多不同的图像分类训练的。因此,这个模型应该已经学习到了健壮的特征层级结构,相对于你的 CNN 模型学到的特征,是空间不变的、转动不变的、平移不变的。因此,这个模型,已经从百万幅图片中学习到了一个好的特征显示,对于像疟疾检测这样的计算机视觉问题,可以作为一个好的合适新图像的特征提取器。在我们的问题中发挥迁移学习的能力之前,让我们先讨论 VGG-19 模型。
|
||||
|
||||
##### 理解 VGG-19 模型
|
||||
|
||||
VGG-19 模型是一个构建在 ImageNet 数据库之上的 19 层(卷积和全连接的)的深度学习网络,该数据库为了图像识别和分类的目的而开发。该模型由 Karen Simonyan 和 Andrew Zisserman 构建,在它们的论文”[大规模图像识别的非常深的卷积网络][22]“中描述。VGG-19 的架构模型是:
|
||||
VGG-19 模型是一个构建在 ImageNet 数据库之上的 19 层(卷积和全连接的)的深度学习网络,ImageNet 数据库为了图像识别和分类的目的而开发。该模型是由 Karen Simonyan 和 Andrew Zisserman 构建的,在他们的论文“[大规模图像识别的非常深的卷积网络][22]”中进行了描述。VGG-19 的架构模型是:
|
||||
|
||||
![VGG-19 模型架构][23]
|
||||
|
||||
你可以看到我们总共有 16 个使用 3x3 卷积过滤器的卷积层,与最大的池化层来下采样,和由 4096 个单元组成的两个全连接的隐藏层,每个隐藏层之后跟随一个由 1000 个单元组成的致密层,每个单元代表 ImageNet 数据库中的一个分类。我们不需要最后三层,因为我们将使用我们自己的全连接致密层来预测疟疾。我们更关心前五块,因此我们可以利用 VGG 模型作为一个有效的特征提取器。
|
||||
你可以看到我们总共有 16 个使用 3x3 卷积过滤器的卷积层,与最大的池化层来下采样,和由 4096 个单元组成的两个全连接的隐藏层,每个隐藏层之后跟随一个由 1000 个单元组成的致密层,每个单元代表 ImageNet 数据库中的一个分类。我们不需要最后三层,因为我们将使用我们自己的全连接致密层来预测疟疾。我们更关心前五个块,因此我们可以利用 VGG 模型作为一个有效的特征提取器。
|
||||
|
||||
我们将使用模型之一作为一个简单的特征提取器通过冻结五个卷积块的方式来确保它们的位权在每个时期后不会更新。对于最后一个模型,我们会应用微调到 VGG 模型,我们会解冻最后两个块(第 4 和第 5)因此当我们训练我们的模型时,它们的位权在每个时期(每批数据)被更新。
|
||||
我们将使用模型之一作为一个简单的特征提取器,通过冻结五个卷积块的方式来确保它们的位权在每个纪元后不会更新。对于最后一个模型,我们会对 VGG 模型进行微调,我们会解冻最后两个块(第 4 和第 5)因此当我们训练我们的模型时,它们的位权在每个时期(每批数据)被更新。
|
||||
|
||||
#### 模型 2:预训练的模型作为一个特征提取器
|
||||
|
||||
为了构建这个模型,我们将利用 TensorFlow 载入 VGG-19 模型并且冻结卷积块因此我们用够将他们用作特征提取器。我们插入我们自己的致密层在末尾来执行分类任务。
|
||||
|
||||
为了构建这个模型,我们将利用 TensorFlow 载入 VGG-19 模型并冻结卷积块,因此我们能够将它们用作特征提取器。我们在末尾插入我们自己的致密层来执行分类任务。
|
||||
|
||||
```
|
||||
vgg = tf.keras.applications.vgg19.VGG19(include_top=False, weights='imagenet',
|
||||
input_shape=INPUT_SHAPE)
|
||||
vgg = tf.keras.applications.vgg19.VGG19(include_top=False, weights='imagenet',
|
||||
input_shape=INPUT_SHAPE)
|
||||
vgg.trainable = False
|
||||
# Freeze the layers
|
||||
for layer in vgg.layers:
|
||||
layer.trainable = False
|
||||
|
||||
layer.trainable = False
|
||||
|
||||
base_vgg = vgg
|
||||
base_out = base_vgg.output
|
||||
pool_out = tf.keras.layers.Flatten()(base_out)
|
||||
@@ -502,37 +497,38 @@ out = tf.keras.layers.Dense(1, activation='sigmoid')(drop2)
|
||||
|
||||
model = tf.keras.Model(inputs=base_vgg.input, outputs=out)
|
||||
model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=1e-4),
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy'])
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy'])
|
||||
model.summary()
|
||||
|
||||
|
||||
# Output
|
||||
Model: "model_1"
|
||||
_________________________________________________________________
|
||||
Layer (type) Output Shape Param #
|
||||
Layer (type) Output Shape Param #
|
||||
=================================================================
|
||||
input_2 (InputLayer) [(None, 125, 125, 3)] 0
|
||||
input_2 (InputLayer) [(None, 125, 125, 3)] 0
|
||||
_________________________________________________________________
|
||||
block1_conv1 (Conv2D) (None, 125, 125, 64) 1792
|
||||
block1_conv1 (Conv2D) (None, 125, 125, 64) 1792
|
||||
_________________________________________________________________
|
||||
block1_conv2 (Conv2D) (None, 125, 125, 64) 36928
|
||||
block1_conv2 (Conv2D) (None, 125, 125, 64) 36928
|
||||
_________________________________________________________________
|
||||
...
|
||||
...
|
||||
_________________________________________________________________
|
||||
block5_pool (MaxPooling2D) (None, 3, 3, 512) 0
|
||||
block5_pool (MaxPooling2D) (None, 3, 3, 512) 0
|
||||
_________________________________________________________________
|
||||
flatten_1 (Flatten) (None, 4608) 0
|
||||
flatten_1 (Flatten) (None, 4608) 0
|
||||
_________________________________________________________________
|
||||
dense_3 (Dense) (None, 512) 2359808
|
||||
dense_3 (Dense) (None, 512) 2359808
|
||||
_________________________________________________________________
|
||||
dropout_2 (Dropout) (None, 512) 0
|
||||
dropout_2 (Dropout) (None, 512) 0
|
||||
_________________________________________________________________
|
||||
dense_4 (Dense) (None, 512) 262656
|
||||
dense_4 (Dense) (None, 512) 262656
|
||||
_________________________________________________________________
|
||||
dropout_3 (Dropout) (None, 512) 0
|
||||
dropout_3 (Dropout) (None, 512) 0
|
||||
_________________________________________________________________
|
||||
dense_5 (Dense) (None, 1) 513
|
||||
dense_5 (Dense) (None, 1) 513
|
||||
=================================================================
|
||||
Total params: 22,647,361
|
||||
Trainable params: 2,622,977
|
||||
@@ -540,45 +536,42 @@ Non-trainable params: 20,024,384
|
||||
_________________________________________________________________
|
||||
```
|
||||
|
||||
输出是很明白的,在我们的模型中我们有了很多层,我们将只利用 VGG-19 模型的冻结层作为特征提取器。你可以使用下列代码来验证我们的模型有多少层是实际训练的,我们的网络中总共存在多少层。
|
||||
|
||||
从整个输出可以明显看出,在我们的模型中我们有了很多层,我们将只利用 VGG-19 模型的冻结层作为特征提取器。你可以使用下列代码来验证我们的模型有多少层是实际可训练的,以及我们的网络中总共存在多少层。
|
||||
|
||||
```
|
||||
print("Total Layers:", len(model.layers))
|
||||
print("Total trainable layers:",
|
||||
sum([1 for l in model.layers if l.trainable]))
|
||||
print("Total trainable layers:",
|
||||
sum([1 for l in model.layers if l.trainable]))
|
||||
|
||||
# Output
|
||||
Total Layers: 28
|
||||
Total trainable layers: 6
|
||||
```
|
||||
|
||||
我们将使用和我们之前的模型相似的配置和回调来训练我们的模型。参考 [我的 GitHub 仓库][24] 获取训练模型的完整代码。我们观察下列显示模型精确度和损失曲线。
|
||||
我们将使用和我们之前的模型相似的配置和回调来训练我们的模型。参考[我的 GitHub 仓库][24]以获取训练模型的完整代码。我们观察下列图表,以显示模型精确度和损失曲线。
|
||||
|
||||
![Learning curves for frozen pre-trained CNN][25]
|
||||
|
||||
冻结的预训练的 CNN 的学习曲线
|
||||
|
||||
这显示了我们的模型没有像我们的基础 CNN 模型那样过拟合,但是性能有点不如我们的基础的 CNN 模型。让我们保存这个模型用户将来的评估。
|
||||
*冻结的预训练的 CNN 的学习曲线*
|
||||
|
||||
这表明我们的模型没有像我们的基础 CNN 模型那样过拟合,但是性能有点不如我们的基础的 CNN 模型。让我们保存这个模型,以备将来的评估。
|
||||
|
||||
```
|
||||
`model.save('vgg_frozen.h5')`
|
||||
model.save('vgg_frozen.h5')
|
||||
```
|
||||
|
||||
#### 模型 3:使用图像增强来微调预训练的模型
|
||||
|
||||
在我们的最后一个模型中,我们微调预定义好的 VGG-19 模型的最后两个块中层的位权。我们同样引入图像增强的概念。图像增强背后的想法和名字一样。我们从训练数据集中载入已存在的图像,并且应用转换操作,例如旋转,裁剪,转换,放大缩小,等等,来产生新的,改变的版本。由于这些随机的转换,我们每次获取到的图像不一样。我们将应用一个在 **tf.keras** 的优秀的工具叫做 **ImageDataGenerator** 来帮助构建图像增强器。
|
||||
|
||||
在我们的最后一个模型中,我们将在预定义好的 VGG-19 模型的最后两个块中微调层的位权。我们同样引入了图像增强的概念。图像增强背后的想法和其名字一样。我们从训练数据集中载入现有图像,并且应用转换操作,例如旋转、裁剪、转换、放大缩小等等,来产生新的、改变过的版本。由于这些随机转换,我们每次获取到的图像不一样。我们将应用 tf.keras 中的一个名为 ImageDataGenerator 的优秀工具来帮助构建图像增强器。
|
||||
|
||||
```
|
||||
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255,
|
||||
zoom_range=0.05,
|
||||
rotation_range=25,
|
||||
width_shift_range=0.05,
|
||||
height_shift_range=0.05,
|
||||
shear_range=0.05, horizontal_flip=True,
|
||||
fill_mode='nearest')
|
||||
zoom_range=0.05,
|
||||
rotation_range=25,
|
||||
width_shift_range=0.05,
|
||||
height_shift_range=0.05,
|
||||
shear_range=0.05, horizontal_flip=True,
|
||||
fill_mode='nearest')
|
||||
|
||||
val_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)
|
||||
|
||||
@@ -587,13 +580,12 @@ train_generator = train_datagen.flow(train_data, train_labels_enc, batch_size=BA
|
||||
val_generator = val_datagen.flow(val_data, val_labels_enc, batch_size=BATCH_SIZE, shuffle=False)
|
||||
```
|
||||
|
||||
我们不会应用任何转换在我们的验证数据集上(除非是调整大小,它是强制性适应的)因为我们将在每个时期来评估我们的模型性能。对于在传输学习上下文中的图像增强的详细解释,请自由查看我们上述引用的[文章][18]。让我们从一批图像增强转换中查看一些样本结果。
|
||||
|
||||
我们不会对我们的验证数据集应用任何转换(除非是调整大小,因为这是必须的),因为我们将使用它评估每个纪元的模型性能。对于在传输学习环境中的图像增强的详细解释,请随时查看我上面引用的[文章][18]。让我们从一批图像增强转换中查看一些样本结果。
|
||||
|
||||
```
|
||||
img_id = 0
|
||||
sample_generator = train_datagen.flow(train_data[img_id:img_id+1], train_labels[img_id:img_id+1],
|
||||
batch_size=1)
|
||||
batch_size=1)
|
||||
sample = [next(sample_generator) for i in range(0,5)]
|
||||
fig, ax = plt.subplots(1,5, figsize=(16, 6))
|
||||
print('Labels:', [item[1][0] for item in sample])
|
||||
@@ -602,24 +594,23 @@ l = [ax[i].imshow(sample[i][0][0]) for i in range(0,5)]
|
||||
|
||||
![Sample augmented images][26]
|
||||
|
||||
你可以清晰的看到与之前的输出中我们图像的轻微变化。我们现在构建我们的学习模型,确保 VGG-19 模型的最后两块是可以训练的。
|
||||
|
||||
你可以清晰的看到与之前的输出的我们图像的轻微变化。我们现在构建我们的学习模型,确保 VGG-19 模型的最后两块是可以训练的。
|
||||
|
||||
```
|
||||
vgg = tf.keras.applications.vgg19.VGG19(include_top=False, weights='imagenet',
|
||||
input_shape=INPUT_SHAPE)
|
||||
vgg = tf.keras.applications.vgg19.VGG19(include_top=False, weights='imagenet',
|
||||
input_shape=INPUT_SHAPE)
|
||||
# Freeze the layers
|
||||
vgg.trainable = True
|
||||
|
||||
set_trainable = False
|
||||
for layer in vgg.layers:
|
||||
if layer.name in ['block5_conv1', 'block4_conv1']:
|
||||
set_trainable = True
|
||||
if set_trainable:
|
||||
layer.trainable = True
|
||||
else:
|
||||
layer.trainable = False
|
||||
|
||||
if layer.name in ['block5_conv1', 'block4_conv1']:
|
||||
set_trainable = True
|
||||
if set_trainable:
|
||||
layer.trainable = True
|
||||
else:
|
||||
layer.trainable = False
|
||||
|
||||
base_vgg = vgg
|
||||
base_out = base_vgg.output
|
||||
pool_out = tf.keras.layers.Flatten()(base_out)
|
||||
@@ -632,31 +623,32 @@ out = tf.keras.layers.Dense(1, activation='sigmoid')(drop2)
|
||||
|
||||
model = tf.keras.Model(inputs=base_vgg.input, outputs=out)
|
||||
model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=1e-5),
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy'])
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy'])
|
||||
|
||||
print("Total Layers:", len(model.layers))
|
||||
print("Total trainable layers:", sum([1 for l in model.layers if l.trainable]))
|
||||
|
||||
|
||||
# Output
|
||||
Total Layers: 28
|
||||
Total trainable layers: 16
|
||||
```
|
||||
|
||||
在我们的模型中我们降低了学习率,因为我们微调的时候不想在预训练的数据集上做大的位权更新。模型的训练过程可能有轻微的不同,因为我们使用了数据生成器,因此我们应用了 **fit_generator(...)** 函数。
|
||||
|
||||
在我们的模型中我们降低了学习率,因为我们不想在微调的时候对预训练的层做大的位权更新。模型的训练过程可能有轻微的不同,因为我们使用了数据生成器,因此我们将应用 `fit_generator(...)` 函数。
|
||||
|
||||
```
|
||||
tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
|
||||
reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5,
|
||||
patience=2, min_lr=0.000001)
|
||||
patience=2, min_lr=0.000001)
|
||||
|
||||
callbacks = [reduce_lr, tensorboard_callback]
|
||||
train_steps_per_epoch = train_generator.n // train_generator.batch_size
|
||||
val_steps_per_epoch = val_generator.n // val_generator.batch_size
|
||||
history = model.fit_generator(train_generator, steps_per_epoch=train_steps_per_epoch, epochs=EPOCHS,
|
||||
validation_data=val_generator, validation_steps=val_steps_per_epoch,
|
||||
verbose=1)
|
||||
validation_data=val_generator, validation_steps=val_steps_per_epoch,
|
||||
verbose=1)
|
||||
|
||||
|
||||
# Output
|
||||
Epoch 1/25
|
||||
@@ -675,21 +667,20 @@ Epoch 25/25
|
||||
|
||||
![Learning curves for fine-tuned pre-trained CNN][27]
|
||||
|
||||
微调预训练的 CNN 的学习曲线
|
||||
*微调过的预训练 CNN 的学习曲线*
|
||||
|
||||
让我们保存这个模型,因此我们能够在测试集上使用。
|
||||
|
||||
|
||||
```
|
||||
`model.save('vgg_finetuned.h5')`
|
||||
model.save('vgg_finetuned.h5')
|
||||
```
|
||||
|
||||
这完成了我们的模型训练阶段。我们准备好在测试集上测试我们模型的性能。
|
||||
这就完成了我们的模型训练阶段。现在我们准备好了在测试集上测试我们模型的性能。
|
||||
|
||||
### 深度学习模型性能评估
|
||||
|
||||
我们将评估我们在训练阶段构建的三个模型,通过在我们的测试集上做预测,因为仅仅验证是不够的!我们同样构建了一个检测工具模块叫做 **model_evaluation_utils**,我们可以使用相关分类指标用来评估使用我们深度学习模型的性能。第一步是测量我们的数据集。
|
||||
|
||||
我们将通过在我们的测试集上做预测来评估我们在训练阶段构建的三个模型,因为仅仅验证是不够的!我们同样构建了一个检测工具模块叫做 `model_evaluation_utils`,我们可以使用相关分类指标用来评估使用我们深度学习模型的性能。第一步是扩展我们的数据集。
|
||||
|
||||
```
|
||||
test_imgs_scaled = test_data / 255.
|
||||
@@ -701,7 +692,6 @@ test_imgs_scaled.shape, test_labels.shape
|
||||
|
||||
下一步包括载入我们保存的深度学习模型,在测试集上预测。
|
||||
|
||||
|
||||
```
|
||||
# Load Saved Deep Learning Models
|
||||
basic_cnn = tf.keras.models.load_model('./basic_cnn.h5')
|
||||
@@ -713,16 +703,15 @@ basic_cnn_preds = basic_cnn.predict(test_imgs_scaled, batch_size=512)
|
||||
vgg_frz_preds = vgg_frz.predict(test_imgs_scaled, batch_size=512)
|
||||
vgg_ft_preds = vgg_ft.predict(test_imgs_scaled, batch_size=512)
|
||||
|
||||
basic_cnn_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
|
||||
for pred in basic_cnn_preds.ravel()])
|
||||
vgg_frz_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
|
||||
for pred in vgg_frz_preds.ravel()])
|
||||
vgg_ft_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
|
||||
for pred in vgg_ft_preds.ravel()])
|
||||
basic_cnn_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
|
||||
for pred in basic_cnn_preds.ravel()])
|
||||
vgg_frz_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
|
||||
for pred in vgg_frz_preds.ravel()])
|
||||
vgg_ft_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
|
||||
for pred in vgg_ft_preds.ravel()])
|
||||
```
|
||||
|
||||
下一步是应用我们的 **model_evaluation_utils** 模块根据相应分类指标来检查每个模块的性能。
|
||||
|
||||
下一步是应用我们的 `model_evaluation_utils` 模块根据相应分类指标来检查每个模块的性能。
|
||||
|
||||
```
|
||||
import model_evaluation_utils as meu
|
||||
@@ -732,30 +721,30 @@ basic_cnn_metrics = meu.get_metrics(true_labels=test_labels, predicted_labels=ba
|
||||
vgg_frz_metrics = meu.get_metrics(true_labels=test_labels, predicted_labels=vgg_frz_pred_labels)
|
||||
vgg_ft_metrics = meu.get_metrics(true_labels=test_labels, predicted_labels=vgg_ft_pred_labels)
|
||||
|
||||
pd.DataFrame([basic_cnn_metrics, vgg_frz_metrics, vgg_ft_metrics],
|
||||
index=['Basic CNN', 'VGG-19 Frozen', 'VGG-19 Fine-tuned'])
|
||||
pd.DataFrame([basic_cnn_metrics, vgg_frz_metrics, vgg_ft_metrics],
|
||||
index=['Basic CNN', 'VGG-19 Frozen', 'VGG-19 Fine-tuned'])
|
||||
```
|
||||
|
||||
![Model accuracy][28]
|
||||
|
||||
看起来我们的第三个模型在我们的测试集上执行的最好,给出了一个模型精确性为 96% 的 F1得分,比起上述我们早期引用的研究论文和文章中提及的复杂的模型是相当好的。
|
||||
看起来我们的第三个模型在我们的测试集上执行的最好,给出了一个模型精确性为 96% 的 F1 得分,这非常好,与我们之前提到的研究论文和文章中的更复杂的模型相当。
|
||||
|
||||
### 总结
|
||||
|
||||
疟疾检测不是一个简单的程序,全球的合格的人员的可获得性在样例诊断和治疗当中是一个严重的问题。我们看到一个关于疟疾的有趣的真实世界的医学影像案例。易于构建的,开源的技术利用 AI 在检测疟疾方面可以给我们最先进的精确性,因此允许 AI 对社会是有益的。
|
||||
疟疾检测不是一个简单的过程,全球的合格人员的不足在病例诊断和治疗当中是一个严重的问题。我们研究了一个关于疟疾的有趣的真实世界的医学影像案例。利用 AI 的、易于构建的、开源的技术在检测疟疾方面可以为我们提供最先进的精确性,因此使 AI 具有社会效益。
|
||||
|
||||
我鼓励你检查这片文章中提到的文章和研究论文,没有它们,我就不能形成概念并写出来。如果你对运行和采纳这些技术感兴趣,本篇文章所有的代码都可以在[我的 GitHub 仓库][24]获得。记得从[官方网站][11]下载数据。
|
||||
我鼓励你查看这篇文章中提到的文章和研究论文,没有它们,我就不能形成概念并写出来。如果你对运行和采纳这些技术感兴趣,本篇文章所有的代码都可以在[我的 GitHub 仓库][24]获得。记得从[官方网站][11]下载数据。
|
||||
|
||||
让我们希望在健康医疗方面更多的采纳开源的 AI 能力,使它在世界范围内变得便宜些,易用些。
|
||||
让我们希望在健康医疗方面更多的采纳开源的 AI 能力,使它在世界范围内变得更便宜、更易用。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/4/detecting-malaria-deep-learning
|
||||
|
||||
作者:[Dipanjan (DJ) Sarkar (Red Hat)][a]
|
||||
作者:[Dipanjan (DJ) Sarkar][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[warmfrog](https://github.com/warmfrog)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (tomjlw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
@@ -109,7 +109,7 @@ via: https://opensource.com/article/19/3/mobile-particulate-matter-sensor
|
||||
|
||||
作者:[Stephan Tetzel][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (3 apps to manage personal finances in Fedora)
|
||||
[#]: via: (https://fedoramagazine.org/3-apps-to-manage-personal-finances-in-fedora/)
|
||||
[#]: author: (Paul W. Frields https://fedoramagazine.org/author/pfrields/)
|
||||
|
||||
3 apps to manage personal finances in Fedora
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
There are numerous services available on the web for managing your personal finances. Although they may be convenient, they also often mean leaving your most valuable personal data with a company you can’t monitor. Some people are comfortable with this level of trust.
|
||||
|
||||
Whether you are or not, you might be interested in an app you can maintain on your own system. This means your data never has to leave your own computer if you don’t want. One of these three apps might be what you’re looking for.
|
||||
|
||||
### HomeBank
|
||||
|
||||
HomeBank is a fully featured way to manage multiple accounts. It’s easy to set up and keep updated. It has multiple ways to categorize and graph income and liabilities so you can see where your money goes. It’s available through the official Fedora repositories.
|
||||
|
||||
![A simple account set up in HomeBank with a few transactions.][2]
|
||||
|
||||
To install HomeBank, open the _Software_ app, search for _HomeBank_ , and select the app. Then click _Install_ to add it to your system. HomeBank is also available via a Flatpak.
|
||||
|
||||
### KMyMoney
|
||||
|
||||
The KMyMoney app is a mature app that has been around for a long while. It has a robust set of features to help you manage multiple accounts, including assets, liabilities, taxes, and more. KMyMoney includes a full set of tools for managing investments and making forecasts. It also sports a huge set of reports for seeing how your money is doing.
|
||||
|
||||
![A subset of the many reports available in KMyMoney.][3]
|
||||
|
||||
To install, use a software center app, or use the command line:
|
||||
|
||||
```
|
||||
$ sudo dnf install kmymoney
|
||||
```
|
||||
|
||||
### GnuCash
|
||||
|
||||
One of the most venerable free GUI apps for personal finance is GnuCash. GnuCash is not just for personal finances. It also has functions for managing income, assets, and liabilities for a business. That doesn’t mean you can’t use it for managing just your own accounts. Check out [the online tutorial and guide][4] to get started.
|
||||
|
||||
![Checking account records shown in GnuCash.][5]
|
||||
|
||||
Open the _Software_ app, search for _GnuCash_ , and select the app. Then click _Install_ to add it to your system. Or use _dnf install_ as above to install the _gnucash_ package.
|
||||
|
||||
It’s now available via Flathub which makes installation easy. If you don’t have Flathub support, check out [this article on the Fedora Magazine][6] for how to use it. Then you can also use the _flatpak install GnuCash_ command with a terminal.
|
||||
|
||||
* * *
|
||||
|
||||
*Photo by _[_Fabian Blank_][7]_ on *[ _Unsplash_][8].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/3-apps-to-manage-personal-finances-in-fedora/
|
||||
|
||||
作者:[Paul W. Frields][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/pfrields/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/04/personal-finance-3-apps-816x345.jpg
|
||||
[2]: https://fedoramagazine.org/wp-content/uploads/2019/04/Screenshot-from-2019-04-28-16-16-16-1024x637.png
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2019/04/Screenshot-from-2019-04-28-16-27-10-1-1024x649.png
|
||||
[4]: https://www.gnucash.org/viewdoc.phtml?rev=3&lang=C&doc=guide
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2019/04/Screenshot-from-2019-04-28-16-41-27-1024x631.png
|
||||
[6]: https://fedoramagazine.org/install-flathub-apps-fedora/
|
||||
[7]: https://unsplash.com/photos/pElSkGRA2NU?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
[8]: https://unsplash.com/search/photos/money?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
@@ -1,261 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (tomjlw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Duc – A Collection Of Tools To Inspect And Visualize Disk Usage)
|
||||
[#]: via: (https://www.ostechnix.com/duc-a-collection-of-tools-to-inspect-and-visualize-disk-usage/)
|
||||
[#]: author: (sk https://www.ostechnix.com/author/sk/)
|
||||
|
||||
Duc – A Collection Of Tools To Inspect And Visualize Disk Usage
|
||||
======
|
||||
|
||||
![Duc - A Collection Of Tools To Inspect And Visualize Disk Usage][1]
|
||||
|
||||
**Duc** is a collection of tools that can be used to index, inspect and visualize disk usage on Unix-like operating systems. Don’t think of it as a simple CLI tool that merely displays a fancy graph of your disk usage. It is built to scale quite well on huge filesystems. Duc has been tested on systems that consisted of more than 500 million files and several petabytes of storage without any problems.
|
||||
|
||||
Duc is quite fast and versatile tool. It stores your disk usage in an optimized database, so you can quickly find where your bytes are as soon as the index is completed. In addition, it comes with various user interfaces and back-ends to access the database and draw the graphs.
|
||||
|
||||
Here is the list of currently supported user interfaces (UI):
|
||||
|
||||
1. Command line interface (ls),
|
||||
2. Ncurses console interface (ui),
|
||||
3. X11 GUI (duc gui),
|
||||
4. OpenGL GUI (duc gui).
|
||||
|
||||
|
||||
|
||||
List of supported database back-ends:
|
||||
|
||||
* Tokyocabinet,
|
||||
* Leveldb,
|
||||
* Sqlite3.
|
||||
|
||||
|
||||
|
||||
Duc uses **Tokyocabinet** as default database backend.
|
||||
|
||||
### Install Duc
|
||||
|
||||
Duc is available in the default repositories of Debian and its derivatives such as Ubuntu. So installing Duc on DEB-based systems is a piece of cake.
|
||||
|
||||
```
|
||||
$ sudo apt-get install duc
|
||||
```
|
||||
|
||||
On other Linux distributions, you may need to manually compile and install Duc from source as shown below.
|
||||
|
||||
Download latest duc source .tgz file from the [**releases**][2] page on github. As of writing this guide, the latest version was **1.4.4**.
|
||||
|
||||
```
|
||||
$ wget https://github.com/zevv/duc/releases/download/1.4.4/duc-1.4.4.tar.gz
|
||||
```
|
||||
|
||||
Then run the following commands one by one to install DUC.
|
||||
|
||||
```
|
||||
$ tar -xzf duc-1.4.4.tar.gz
|
||||
$ cd duc-1.4.4
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
### Duc Usage
|
||||
|
||||
The typical usage of duc is:
|
||||
|
||||
```
|
||||
$ duc <subcommand> <options>
|
||||
```
|
||||
|
||||
You can view the list of general options and sub-commands by running the following command:
|
||||
|
||||
```
|
||||
$ duc help
|
||||
```
|
||||
|
||||
You can also know the the usage of a specific subcommand as below.
|
||||
|
||||
```
|
||||
$ duc help <subcommand>
|
||||
```
|
||||
|
||||
To view the extensive list of all commands and their options, simply run:
|
||||
|
||||
```
|
||||
$ duc help --all
|
||||
```
|
||||
|
||||
Let us now se some practical use cases of duc utility.
|
||||
|
||||
### Create Index (database)
|
||||
|
||||
First of all, you need to create an index file (database) of your filesystem. To create an index file, use “duc index” command.
|
||||
|
||||
For example, to create an index of your **/home** directory, simply run:
|
||||
|
||||
```
|
||||
$ duc index /home
|
||||
```
|
||||
|
||||
The above command will create the index of your /home/ directory and save it in **$HOME/.duc.db** file. If you have added new files/directories in the /home directory in future, just re-run the above command at any time later to rebuild the index.
|
||||
|
||||
### Query Index
|
||||
|
||||
Duc has various sub-commands to query and explore the index.
|
||||
|
||||
To view the list of available indexes, run:
|
||||
|
||||
```
|
||||
$ duc info
|
||||
```
|
||||
|
||||
**Sample output:**
|
||||
|
||||
```
|
||||
Date Time Files Dirs Size Path
|
||||
2019-04-09 15:45:55 3.5K 305 654.6M /home
|
||||
```
|
||||
|
||||
As you see in the above output, I have already indexed the /home directory.
|
||||
|
||||
To list all files and directories in the current working directory, you can do:
|
||||
|
||||
```
|
||||
$ duc ls
|
||||
```
|
||||
|
||||
To list files/directories in a specific directory, for example **/home/sk/Downloads** , just pass the path as argument like below.
|
||||
|
||||
```
|
||||
$ duc ls /home/sk/Downloads
|
||||
```
|
||||
|
||||
Similarly, run **“duc ui”** command to open a **ncurses** based console user interface for exploring the file system usage and run **“duc gui”** to start a **graphical (X11)** interface to explore the file system.
|
||||
|
||||
To know more about a sub-command usage, simply refer the help section.
|
||||
|
||||
```
|
||||
$ duc help ls
|
||||
```
|
||||
|
||||
The above command will display the help section of “ls” subcommand.
|
||||
|
||||
### Visualize Disk Usage
|
||||
|
||||
In the previous section, we have seen how to list files and directories using duc subcommands. In addition, you can even show the file sizes in a fancy graph.
|
||||
|
||||
To show the graph of a given path, use “ls” subcommand like below.
|
||||
|
||||
```
|
||||
$ duc ls -Fg /home/sk
|
||||
```
|
||||
|
||||
Sample output:
|
||||
|
||||
![][3]
|
||||
|
||||
Visualize disk usage using “duc ls” command
|
||||
|
||||
As you see in the above output, the “ls” subcommand queries the duc database and lists the inclusive size of all
|
||||
files and directories of the given path i.e **/home/sk/** in this case.
|
||||
|
||||
Here, the **“-F”** option is used to append file type indicator (one of */) to entries and the **“-g”** option is used to draw graph with relative size for each entry.
|
||||
|
||||
Please note that if no path is given, the current working directory is explored.
|
||||
|
||||
You can use **-R** option to view the disk usage result in [**tree**][4] structure.
|
||||
|
||||
```
|
||||
$ duc ls -R /home/sk
|
||||
```
|
||||
|
||||
![][5]
|
||||
|
||||
Visualize disk usage in tree structure
|
||||
|
||||
To query the duc database and open a **ncurses** based console user interface for exploring the disk usage of given path, use **“ui”** subcommand like below.
|
||||
|
||||
```
|
||||
$ duc ui /home/sk
|
||||
```
|
||||
|
||||
![][6]
|
||||
|
||||
Similarly, we use **“gui”** subcommand to query the duc database and start a **graphical (X11)** interface to explore the disk usage of the given path:
|
||||
|
||||
```
|
||||
$ duc gui /home/sk
|
||||
```
|
||||
|
||||
![][7]
|
||||
|
||||
Like I already mentioned earlier, we can learn more about a subcommand usage like below.
|
||||
|
||||
```
|
||||
$ duc help <subcommand-name>
|
||||
```
|
||||
|
||||
I covered the basic usage part only. Refer man pages for more details about “duc” tool.
|
||||
|
||||
```
|
||||
$ man duc
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
**Related read:**
|
||||
|
||||
* [**Filelight – Visualize Disk Usage On Your Linux System**][8]
|
||||
* [**Some Good Alternatives To ‘du’ Command**][9]
|
||||
* [**How To Check Disk Space Usage In Linux Using Ncdu**][10]
|
||||
* [**Agedu – Find Out Wasted Disk Space In Linux**][11]
|
||||
* [**How To Find The Size Of A Directory In Linux**][12]
|
||||
* [**The df Command Tutorial With Examples For Beginners**][13]
|
||||
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
### Conclusion
|
||||
|
||||
Duc is simple yet useful disk usage viewer. If you want to quickly and easily know which files/directories are eating up your disk space, Duc might be a good choice. What are you waiting for? Go get this tool already, scan your filesystem and get rid of unused files/directories.
|
||||
|
||||
And, that’s all for now. Hope this was useful. More good stuffs to come. Stay tuned!
|
||||
|
||||
Cheers!
|
||||
|
||||
**Resource:**
|
||||
|
||||
* [**Duc website**][14]
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/duc-a-collection-of-tools-to-inspect-and-visualize-disk-usage/
|
||||
|
||||
作者:[sk][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.ostechnix.com/wp-content/uploads/2019/04/duc-720x340.png
|
||||
[2]: https://github.com/zevv/duc/releases
|
||||
[3]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-1-1.png
|
||||
[4]: https://www.ostechnix.com/view-directory-tree-structure-linux/
|
||||
[5]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-2.png
|
||||
[6]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-3.png
|
||||
[7]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-4.png
|
||||
[8]: https://www.ostechnix.com/filelight-visualize-disk-usage-on-your-linux-system/
|
||||
[9]: https://www.ostechnix.com/some-good-alternatives-to-du-command/
|
||||
[10]: https://www.ostechnix.com/check-disk-space-usage-linux-using-ncdu/
|
||||
[11]: https://www.ostechnix.com/agedu-find-out-wasted-disk-space-in-linux/
|
||||
[12]: https://www.ostechnix.com/find-size-directory-linux/
|
||||
[13]: https://www.ostechnix.com/the-df-command-tutorial-with-examples-for-beginners/
|
||||
[14]: https://duc.zevv.nl/
|
||||
@@ -0,0 +1,73 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (3 apps to manage personal finances in Fedora)
|
||||
[#]: via: (https://fedoramagazine.org/3-apps-to-manage-personal-finances-in-fedora/)
|
||||
[#]: author: (Paul W. Frields https://fedoramagazine.org/author/pfrields/)
|
||||
|
||||
3 款在 Fedora 中管理个人财务的应用
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
网上有很多可以用来管理你个人财务的服务。虽然它们可能很方便,但这通常也意味着将你最宝贵的个人数据放在你无法监控的公司。也有些人对这些不太在意。
|
||||
|
||||
无论你是否在意,你可能会对你自己系统上的应用感兴趣。这意味着如果你不想,你的数据永远不会离开莫自己的计算机。这三款之一可能就是你想找的。
|
||||
|
||||
### HomeBank
|
||||
|
||||
HomeBank 是一款可以管理多个账户的全功能软件。它很容易设置并保持更新。它有多种方式画出你的分类和负载,以便你可以看到资金流向何处。它可以通过官方 Fedora 仓库下载。
|
||||
|
||||
![A simple account set up in HomeBank with a few transactions.][2]
|
||||
|
||||
要安装 HomeBank,请打开_软件中心_,搜索 _HomeBank_,然后选择该应用。单击_安装_将其添加到你的系统中。HomeBank 也可以通过 Flatpak 安装。
|
||||
|
||||
### KMyMoney
|
||||
|
||||
KMyMoney 是一个成熟的应用,它已经存在了很长一段时间。它有一系列稳定的功能,可帮助你管理多个帐户,包括资产、负债、税收等。KMyMoney 包含一整套用于管理投资和进行预测的工具。它还提供大量报告,以了解你的资金运作方式。
|
||||
|
||||
![A subset of the many reports available in KMyMoney.][3]
|
||||
|
||||
要安装它,请使用软件中心,或使用命令行:
|
||||
|
||||
```
|
||||
$ sudo dnf install kmymoney
|
||||
```
|
||||
|
||||
### GnuCash
|
||||
|
||||
用于个人财务的最受欢迎的免费 GUI 应用之一是 GnuCash。GnuCash 不仅可以用于个人财务。它还有管理企业收入、资产和负债的功能。这并不意味着你不能用它来管理自己的账户。从查看[在线教程和指南][4]开始了解。
|
||||
|
||||
![Checking account records shown in GnuCash.][5]
|
||||
|
||||
打开_软件中心_,搜索 _GnuCash_,然后选择应用。单击_安装_将其添加到你的系统中。或者如上所述使用 _dnf install_ 来安装 _gnucash_ 包。
|
||||
|
||||
它现在可以通过 Flathub 安装,这使得安装变得简单。如果你没有安装 Flathub,请查看 [Fedora Magazine 上的这篇文章][6]了解如何使用它。这样你也可以在终端使用 _flatpak install GnuCash_ 命令。
|
||||
|
||||
* * *
|
||||
|
||||
照片由 _[_Fabian Blank_][7]_ 拍摄,发布在 [ _Unsplash_][8] 上。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/3-apps-to-manage-personal-finances-in-fedora/
|
||||
|
||||
作者:[Paul W. Frields][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/pfrields/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/04/personal-finance-3-apps-816x345.jpg
|
||||
[2]: https://fedoramagazine.org/wp-content/uploads/2019/04/Screenshot-from-2019-04-28-16-16-16-1024x637.png
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2019/04/Screenshot-from-2019-04-28-16-27-10-1-1024x649.png
|
||||
[4]: https://www.gnucash.org/viewdoc.phtml?rev=3&lang=C&doc=guide
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2019/04/Screenshot-from-2019-04-28-16-41-27-1024x631.png
|
||||
[6]: https://fedoramagazine.org/install-flathub-apps-fedora/
|
||||
[7]: https://unsplash.com/photos/pElSkGRA2NU?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
[8]: https://unsplash.com/search/photos/money?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
@@ -0,0 +1,257 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (tomjlw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Duc – A Collection Of Tools To Inspect And Visualize Disk Usage)
|
||||
[#]: via: (https://www.ostechnix.com/duc-a-collection-of-tools-to-inspect-and-visualize-disk-usage/)
|
||||
[#]: author: (sk https://www.ostechnix.com/author/sk/)
|
||||
|
||||
Duc——一个能够洞察并可视化硬盘使用情况的工具包
|
||||
======
|
||||
|
||||
![Duc——一个能够洞察并可视化硬盘使用情况的工具包][1]
|
||||
|
||||
**Duc** 是一个在类 Unix 操作系统上可以用来索引、洞察及可视化硬盘使用情况的工具包。别把它当成一个仅能用漂亮图表展现硬盘使用情况的 CLI 工具。它被设计成在巨大的文件系统上也可以延展得很好。Duc 已在由超过五亿个文件和几 PB 的存储组成的系统上测试过,没有任何问题。
|
||||
|
||||
Duc 是一个快速而且多变的工具。它将你的硬盘使用情况存在一个优化过的数据库里,这样你就可以在索引完成后迅速找到你的数据。此外,它自带不同的用户交互界面与后端以访问数据库并绘制图表。
|
||||
|
||||
以下列出的是目前支持的用户界面(UI):
|
||||
|
||||
1. 命令行界面 (ls),
|
||||
2. Ncurses 控制台界面 (ui),
|
||||
3. X11 GUI (duc gui),
|
||||
4. OpenGL GUI (duc gui)。
|
||||
|
||||
|
||||
|
||||
支持的后端数据库:
|
||||
|
||||
* Tokyocabinet,
|
||||
* Leveldb,
|
||||
* Sqlite3.
|
||||
|
||||
|
||||
|
||||
Duc 使用 **Tokyocabinet** 作为默认的后端数据库。
|
||||
|
||||
### 安装 Duc
|
||||
|
||||
Duc 可以从 Debian 以及其衍生品例如 Ubuntu 的默认仓库中获取。因此在基于 DEB 的系统上安装 Duc 小菜一碟。
|
||||
|
||||
```
|
||||
$ sudo apt-get install duc
|
||||
```
|
||||
|
||||
在其它 Linux 发行版上你需要像以下所展示的那样手动从源编译安装 Duc。
|
||||
|
||||
从 github 上的[**发行**][2]页面下载最新的 Duc 源 .tgz 文件。在写这篇教程的时候,最新的版本是**1.4.4**。
|
||||
|
||||
```
|
||||
$ wget https://github.com/zevv/duc/releases/download/1.4.4/duc-1.4.4.tar.gz
|
||||
```
|
||||
|
||||
然后一个接一个地运行以下命令来安装 DUC。
|
||||
|
||||
```
|
||||
$ tar -xzf duc-1.4.4.tar.gz
|
||||
$ cd duc-1.4.4
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
### 使用 Duc
|
||||
|
||||
duc 的典型用法是:
|
||||
|
||||
```
|
||||
$ duc <subcommand> <options>
|
||||
```
|
||||
|
||||
你可以通过运行以下命令来浏览总的选项列表以及副命令:
|
||||
|
||||
```
|
||||
$ duc help
|
||||
```
|
||||
|
||||
你也可以像下面这样了解一个特定副命令的用法。
|
||||
|
||||
```
|
||||
$ duc help <subcommand>
|
||||
```
|
||||
|
||||
要查看所有命令与其选项的列表,仅需运行:
|
||||
|
||||
```
|
||||
$ duc help --all
|
||||
```
|
||||
|
||||
让我们看看一些 duc 工具的特定用法。
|
||||
|
||||
### 创建索引(数据库)
|
||||
|
||||
首先,你需要创建一个你文件系统的索引文件(数据库)。使用“duc index”命令以创建索引文件。
|
||||
|
||||
比如说,要创建你的 **/home** 目录的索引,仅需运行:
|
||||
|
||||
```
|
||||
$ duc index /home
|
||||
```
|
||||
|
||||
上述命令将会创建你的 /home/ 目录的索引并将其保存在 **$HOME/.duc.db** 文件中。如果你以后需要往 /home 目录添加新的文件/目录,只要在之后重新运行一下上面的命令来重建索引。
|
||||
|
||||
### 查询索引
|
||||
|
||||
Duc 有不同的副命令来查询并探索索引。
|
||||
|
||||
要查看可访问的索引列表,运行:
|
||||
|
||||
```
|
||||
$ duc info
|
||||
```
|
||||
|
||||
**示例输出:**
|
||||
|
||||
```
|
||||
日期 时间 文件 目录 大小 路径
|
||||
2019-04-09 15:45:55 3.5K 305 654.6M /home
|
||||
```
|
||||
|
||||
如你在上述输出所见,我已经索引好了 /home 目录。
|
||||
|
||||
要列出当前工作目录中所有的文件和目录,你可以这样做:
|
||||
|
||||
```
|
||||
$ duc ls
|
||||
```
|
||||
|
||||
要列出所提供目录例如 **/home/sk/Downloads** 中的文件/目录,仅需像下面这样将路径作为参数传过去。
|
||||
|
||||
```
|
||||
$ duc ls /home/sk/Downloads
|
||||
```
|
||||
|
||||
类似的,运行**“duc ui”**命令来打开基于 **ncurses** 的控制台用户界面以探索文件系统使用情况,运行**“duc gui”**以打开 **graphical (X11)** 界面来探索文件系统。
|
||||
|
||||
要了解更多副命令的用法,仅需参考帮助部分。
|
||||
|
||||
```
|
||||
$ duc help ls
|
||||
```
|
||||
|
||||
上述命令将会展现 “ls” 副命令的帮助部分。
|
||||
|
||||
### 可视化硬盘使用状况
|
||||
|
||||
在之前的部分我们以及看到如何用 duc 副命令列出文件和目录。在此之外,你甚至可以用一张漂亮的图表展示文件大小。
|
||||
|
||||
要展示所提供目录的图表,像以下这样使用“ls”副命令。
|
||||
|
||||
```
|
||||
$ duc ls -Fg /home/sk
|
||||
```
|
||||
|
||||
示例输出:
|
||||
|
||||
![使用 “duc ls” 命令可视化硬盘使用情况][3]
|
||||
|
||||
如你在上述输出所见,“ls”副命令查询 duc 数据库并列出了所提供目录,在这里就是 **/home/sk/**,所包含的文件与目录的大小。
|
||||
|
||||
这里 **-F** 选项是往条目中用来添加文件类型显示(*/之一),**-g** 选项是用来绘制每个条目相对大小的图表。
|
||||
|
||||
请注意如果未提供任何路径,当前工作目录就会被探索。
|
||||
|
||||
你可以使用 **-R** 选项来用[**树状结构**][4]浏览硬盘使用情况。
|
||||
|
||||
```
|
||||
$ duc ls -R /home/sk
|
||||
```
|
||||
|
||||
![用树状结构可视化硬盘使用情况][5]
|
||||
|
||||
要查询 duc 数据库并打开基于 **ncurses** 的控制台以探索所提供的目录,像以下这样使用**“ui”**副命令。
|
||||
|
||||
```
|
||||
$ duc ui /home/sk
|
||||
```
|
||||
|
||||
![][6]
|
||||
|
||||
类似的,我们使用**“gui”* 副命令来查询 duc 数据库以及打开一个 **graphical (X11)** 界面来探索提供路径的硬盘使用情况。
|
||||
|
||||
```
|
||||
$ duc gui /home/sk
|
||||
```
|
||||
|
||||
![][7]
|
||||
|
||||
像我之前所提到的,我们可以像下面这样了解更多关于特定副命令的用法。
|
||||
|
||||
```
|
||||
$ duc help <副命令名字>
|
||||
```
|
||||
|
||||
我仅仅覆盖了基本用法的部分,参考 man 页面了解关于“duc”工具的更多细节。
|
||||
|
||||
```
|
||||
$ man duc
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
**相关阅读:**
|
||||
|
||||
* [**Filelight – 在你的 Linux 系统上可视化硬盘使用情况**][8]
|
||||
* [**一些好的‘du’命令的替代品**][9]
|
||||
* [**如何在 Linux 中用 Ncdu 检查硬盘使用情况**][10]
|
||||
* [**Agedu——发现 Linux 中被浪费的硬盘空间**][11]
|
||||
* [**如何在 Linux 中找到目录大小**][12]
|
||||
* [**为初学者打造的带有示例的 df 命令教程**][13]
|
||||
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
### 总结
|
||||
|
||||
Duc 是一款简单却有用的硬盘使用查看器。如果你想要快速简便地知道哪个文件/目录占用你的硬盘空间,Duc 可能是一个好的选择。你还等什么呢?获取这个工具,扫描你的文件系统,摆脱无用的文件/目录。
|
||||
|
||||
现在就到此为止了。希望这篇文章有用处。更多好东西马上就到。保持关注!
|
||||
|
||||
欢呼吧!
|
||||
|
||||
**资源:**
|
||||
|
||||
|
||||
* [**Duc 网站**][14]
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/duc-a-collection-of-tools-to-inspect-and-visualize-disk-usage/
|
||||
|
||||
作者:[sk][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[tomjlw](https://github.com/tomjlw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.ostechnix.com/wp-content/uploads/2019/04/duc-720x340.png
|
||||
[2]: https://github.com/zevv/duc/releases
|
||||
[3]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-1-1.png
|
||||
[4]: https://www.ostechnix.com/view-directory-tree-structure-linux/
|
||||
[5]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-2.png
|
||||
[6]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-3.png
|
||||
[7]: http://www.ostechnix.com/wp-content/uploads/2019/04/duc-4.png
|
||||
[8]: https://www.ostechnix.com/filelight-visualize-disk-usage-on-your-linux-system/
|
||||
[9]: https://www.ostechnix.com/some-good-alternatives-to-du-command/
|
||||
[10]: https://www.ostechnix.com/check-disk-space-usage-linux-using-ncdu/
|
||||
[11]: https://www.ostechnix.com/agedu-find-out-wasted-disk-space-in-linux/
|
||||
[12]: https://www.ostechnix.com/find-size-directory-linux/
|
||||
[13]: https://www.ostechnix.com/the-df-command-tutorial-with-examples-for-beginners/
|
||||
[14]: https://duc.zevv.nl/
|
||||
Reference in New Issue
Block a user