写点什么

使用 Amazon Textract 和 Amazon Comprehend Medical 实现无服务器化的医疗文档分析(一)

  • 2020-01-09
  • 本文字数:5875 字

    阅读完需:约 19 分钟

使用 Amazon Textract 和 Amazon Comprehend Medical 实现无服务器化的医疗文档分析(一)

场景概述

  • 在医学报告整理和内容提取的场景中,从业人员往往需要花费大量的时间进行内容阅读和关键字的提炼;Amazon Textract 结合 Amazon Comprehend Medical 的解决方案整体采用无服务器化架构,全自动化也提高整体效率。采用该解决方案,可以以秒级的效率提取出需要的内容;除此之外,该架构也大大降低了整体成本,架构中包含的所有服务都以实际使用计费。

  • Amazon Textract 是一个托管的 OCR(Optical Character Recognition) 服务,Amazon Comprehend Medical 是一个医疗语义分析的托管人工智能服务。通过 Amazon Textract 将医学报告和诊断报告的表单表格转化成序列化文档,通过 Amazon Comprehend Medical 对这些序列化文档进行分析并快速获取不同分类的信息。在 CRO(Clinical Research Organization) 等行业场景中,可以通过这个解决方案对医学研究、药物分析及诊断报告提供有效的帮助和补充。

服务架构

  • 在这个架构中,我们需要创建:

  • 一个 Amazon S3 存储桶用来存放输入的文档资料和输出的结果文件

  • 一个用来调用 Amazon Textract API 的 AWS Lambda 函数

  • 一个用来调用 Amazon Comprehend Medical API 的 AWS Lambda 函数



架构逻辑如下:


  1. 以用户向 Amazon S3 传入一个文档为例,上传成功后 AWS Lambda 函数会以该事件作为触发并调用 Amazon Textract API,将该文档内容提取成序列化的文档以及待分析的文本,并存入 Amazon S3 的相应路径

  2. 上述待分析文本传入 Amazon S3 后,又会触发下一个 AWS Lambda 函数,调用 Amazon Comprehend Medical API,对内容进行语义分析,并将分析后的结果写入 Amazon S3

  3. 完成以上自动化的操作后,用户即可查询读取提炼后的内容进行进一步的工作

具体实现

Amazon S3 存储桶配置

  • 创建用于输入和输出医学分析报告的存储桶和桶下面相应目录,例如:

  • 存储桶:s3://medical-report-analysis-<unique_identifier>

  • 这里的<unique_identifier> 用以和其他用户的 S3 存储桶区分,因为 Amazon S3 存储桶的名称具有全球唯一性

  • 文档输入目录:s3://medical-report-analysis-<unique_identifier>/input

  • 手动检查目录:s3://medical-report-analysis-<unique_identifier>/manual

  • 分析输入目录:s3://medical-report-analysis-<unique_identifier>/medical

  • 保护数据目录:s3://medical-report-analysis-<unique_identifier>/phi

  • 原始文档目录:s3://medical-report-analysis-<unique_identifier>/raw

  • 分析结果目录:s3://medical-report-analysis-<unique_identifier>/result



  • 启用 Amazon S3 的版本控制

AWS IAM 权限配置

由于整体技术实现会通过 AWS Lambda 作为粘合剂将几个服务串联起来,所以需要创建相应的 AWS IAM 角色以确保服务之间有权限进行相互调用;以下会创建用于串接 Amazon S3 和 Amazon Textract 的 AWS IAM Role,以及用于串接 Amazon S3 和 Amazon Comprehend Medical 的 AWS IAM Role:


  1. 创建用于串接 Amazon S3 和 Amazon Textract 的 AWS IAM Policy:

  2. 策略名称:LAMBDA_TEXTRACT_S3_RW

  3. 策略文档:


Python


{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Action": [        "textract:*",        "s3:*",        "cloudwatch:*",        "logs:*",        "iam:GetPolicy",        "iam:GetPolicyVersion",        "iam:GetRole"      ],      "Resource": "*"    },    {      "Effect": "Allow",      "Action": "iam:CreateServiceLinkedRole",      "Resource": "arn:aws:iam::*:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents*",      "Condition": {        "StringLike": {          "iam:AWSServiceName": "events.amazonaws.com"        }      }    }  ]}
复制代码


  1. 创建用于串接 Amazon S3 和 Amazon Textract 的 AWS IAM Role:

  2. 受信任实体:Lambda

  3. 绑定策略:LAMBDA_TEXTRACT_S3_RW

  4. 角色名称:LAMBDA_TEXTRACT_S3_RW_ALL

  5. 创建用于串接 Amazon S3 和 Amazon Comprehend Medical 的 AWS IAM Policy:

  6. 策略名称:LAMBDA_COMPREHENDMEDICAL_S3_RW

  7. 策略文档:


Python


{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Action": [        "comprehendmedical:*",        "s3:*",        "cloudwatch:*",        "logs:*",        "iam:GetPolicy",        "iam:GetPolicyVersion",        "iam:GetRole"      ],      "Resource": "*"    },    {      "Effect": "Allow",      "Action": "iam:CreateServiceLinkedRole",      "Resource": "arn:aws:iam::*:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents*",      "Condition": {        "StringLike": {          "iam:AWSServiceName": "events.amazonaws.com"        }      }    }  ]}
复制代码


  1. 创建用于串接 Amazon S3 和 Amazon Textract 的 AWS IAM Role:

  2. 受信任实体:Lambda

  3. 绑定策略:LAMBDA_COMPREHENDMEDICAL_S3_RW

  4. 角色名称:LAMBDA_COMPREHENDMEDICAL_S3_RW_ALL

AWS Lambda 函数 – textract_content_ingest

  1. 函数名称:textract_content_ingest

  2. 运行时:Python 3.8

  3. 执行角色:LAMBDA_TEXTRACT_S3_RW_ALL

  4. 内存分配:1024 MB

  5. 超时:1 分钟

  6. 代码如下:


Python


import boto3import json
def lambda_handler(event, context): # File definition s3Key = event['Records'][0]['s3']['object']['key'] keyName = s3Key.split('/')[1].split('.')[0] outFile = '/tmp/output.json' outputKey = 'raw/' + keyName + '/raw.json' medicalRaw = "/tmp/medicalraw.txt" medicalRawKey = 'raw/' + keyName + '/medicalraw.txt' medicalReport = '/tmp/medicalreport.txt' medicalReportKey = 'medical/' + keyName + '/medicalreport.txt'
# S3 and Textract Configuration s3Bucket = event['Records'][0]['s3']['bucket']['name'] fileType = 'FORMS'
# Call Textract to convert form to json textract = boto3.client('textract') textractResponse = textract.analyze_document( Document={ 'S3Object': { 'Bucket': s3Bucket, 'Name': s3Key } }, FeatureTypes=[ fileType ] ) with open(outFile, 'w') as outfile: outfile.write(json.dumps(textractResponse, indent=4))
# Ingest content for blocks in textractResponse['Blocks'][1:]: if blocks['Confidence']: if (blocks['Confidence'] >= 70) and (blocks['BlockType'] == 'LINE'): with open(medicalReport, 'a') as medicalReportOut: medicalReportOut.write(blocks['Text'] + "\r\n") elif (blocks['Confidence'] >= 70) and (blocks['BlockType'] == 'WORD'): with open(medicalRaw, 'a') as medicalRawOut: medicalRawOut.write(blocks['Text'] + "\r\n") else: continue else: print("oops")
# Upload outputs to s3 s3 = boto3.resource('s3') try: s3.meta.client.upload_file(outFile, s3Bucket, outputKey) s3.meta.client.upload_file(medicalReport, s3Bucket, medicalReportKey) s3.meta.client.upload_file(medicalRaw, s3Bucket, medicalRawKey) except Exception as e: print(e) print("Upload failed!") else: print("Upload done!")
复制代码

AWS Lambda 函数 – comprehendmedical_analysis

  1. 函数名称:comprehendmedical_analysis

  2. 运行时:Python 3.8

  3. 执行角色:LAMBDA_COMPREHENDMEDICAL_S3_RW_ALL

  4. 内存分配:1024 MB

  5. 超时:1 分钟

  6. 代码如下:


Python


import boto3import json
def lambda_handler(event, context): # Configure definition s3Bucket = event['Records'][0]['s3']['bucket']['name'] s3Key = event['Records'][0]['s3']['object']['key'] keyName = s3Key.split('/')[1].split('.')[0] localFinal = '/tmp/result.txt' phiFinal = '/tmp/phi.txt' manualFinal = '/tmp/manual.txt' medicalResult = 'result/' + keyName + '/medicalresult.txt' phiResult = 'phi/' + keyName + '/phi.txt' manualResult = 'manual/' + keyName + '/manual.txt'
# Ingest medical report try: s3 = boto3.client('s3') except Exception as e: print(e) print('connect S3 failed!') else: print('connect S3 successfully')
s3_object = s3.get_object(Bucket=s3Bucket, Key=s3Key) body = s3_object['Body']
# Execute medical analysis try: comprehendMedical = boto3.client('comprehendmedical') except Exception as e: print(e) else: print('connect Comprehend Medical successfully')
detectEntities = comprehendMedical.detect_entities_v2( Text=body.read().decode('utf-8') ) detectOutputRaw = detectEntities['Entities']
# Categorize different types of information report_ANATOMY = [] report_MEDICAL_CONDITION = [] report_MEDICATION = [] report_PROTECTED_HEALTH_INFORMATION = [] report_TEST_TREATMENT_PROCEDURE = [] report_MANUAL = []
for ctgy in detectOutputRaw: if ctgy['Score'] >= 0.6: if ctgy['Category'] == 'ANATOMY': report_ANATOMY.append(ctgy) elif ctgy['Category'] == 'MEDICAL_CONDITION': report_MEDICAL_CONDITION.append(ctgy) elif ctgy['Category'] == 'MEDICATION': report_MEDICATION.append(ctgy) elif ctgy['Category'] == 'PROTECTED_HEALTH_INFORMATION': report_PROTECTED_HEALTH_INFORMATION.append(ctgy) elif ctgy['Category'] == 'TEST_TREATMENT_PROCEDURE': report_TEST_TREATMENT_PROCEDURE.append(ctgy) else: continue else: report_MANUAL.append(ctgy)
result_ANATOMY = [] result_MEDICAL_CONDITION = [] result_MEDICATION = [] result_PROTECTED_HEALTH_INFORMATION = [] result_TEST_TREATMENT_PROCEDURE = [] result_MANUAL = []
if report_ANATOMY: for anatomy in report_ANATOMY: result_ANATOMY.append(anatomy['Text']) if report_MEDICAL_CONDITION: for medical_condition in report_ANATOMY: result_MEDICAL_CONDITION.append(medical_condition['Text']) if report_MEDICATION: for medication in report_MEDICATION: result_MEDICATION.append(medication['Text']) if report_PROTECTED_HEALTH_INFORMATION: for protected_health_information in report_PROTECTED_HEALTH_INFORMATION: result_PROTECTED_HEALTH_INFORMATION.append(protected_health_information['Text']) if report_TEST_TREATMENT_PROCEDURE: for test_treatment_procedure in report_TEST_TREATMENT_PROCEDURE: result_TEST_TREATMENT_PROCEDURE.append(test_treatment_procedure['Text']) if report_MANUAL: for test_manual in report_MANUAL: result_MANUAL.append(test_manual['Text'])
with open(localFinal, 'a') as localfile: if result_ANATOMY: localfile.write('Anatomy:\r\n' + '\r\n'.join(set(result_ANATOMY))) if result_MEDICAL_CONDITION: localfile.write('\r\n---\r\n') localfile.write('Medical Condition:\r\n' + '\r\n'.join(set(result_MEDICAL_CONDITION))) if result_MEDICATION: localfile.write('\r\n---\r\n') localfile.write('Medication:\r\n' + '\r\n'.join(set(result_MEDICATION))) if result_TEST_TREATMENT_PROCEDURE: localfile.write('\r\n---\r\n') localfile.write('Test Treatment Procedure:\r\n' + '\r\n'.join(set(result_TEST_TREATMENT_PROCEDURE))) localfile.close()
with open(phiFinal, 'a') as phifile: if result_PROTECTED_HEALTH_INFORMATION: phifile.write('Protected Health Information:\r\n' + '\r\n'.join(set(result_PROTECTED_HEALTH_INFORMATION))) phifile.close()
with open(manualFinal, 'a') as manualfile: if result_MANUAL: manualfile.write('Manually Check:\r\n' + '\r\n'.join(set(result_MANUAL))) manualfile.close()
# Upload outputs to s3 s3Upload = boto3.resource('s3') try: s3Upload.meta.client.upload_file(localFinal, s3Bucket, medicalResult) s3Upload.meta.client.upload_file(phiFinal, s3Bucket, phiResult) s3Upload.meta.client.upload_file(manualFinal, s3Bucket, manualResult)
except Exception as e: print(e) print("Upload failed!") else: print("Upload done!")
复制代码

Amazon S3 事件与 AWS Lambda 集成

  1. 使用拥有 Amazon S3 管理权限的用户登录 AWS 管理控制台

  2. 进入到相应的 Amazon S3 存储桶 (medical-report-analysis-<unique_identifier>)

  3. 切换到“属性”选项卡,点开“事件”

  4. 点击“添加通知”,输入名称“upload_report”,事件勾选 “PUT”,前缀处输入 “input/”,发送到选择 AWS Lambda,选择函数 textract_content_ingest,然后选择保存

  5. 点击“添加通知”,输入名称“comprehendmedical_analysis”,事件勾选 “PUT”,前缀处输入 “medical/”,发送到选择 AWS Lambda,选择函数 comprehendmedical_analysis,然后选择保存


本文转载自 AWS 技术博客。


原文链接:https://amazonaws-china.com/cn/blogs/china/serverless-medical-document-analysis-with-amazon-textract-and-amazon-comprehend-medical/


2020-01-09 15:571015

评论

发布
暂无评论
发现更多内容

干货|语义网、Web3.0、Web3、元宇宙这些概念还傻傻分不清楚?(中)

Orillusion

开源 WebGL 元宇宙 Metaverse webgpu

「中高级试题」:MVCC实现原理是什么?

程序员啊叶

Java 编程 程序员 架构 java面试

聚力打造四个“高地”,携手合作伙伴共铸国云!

天翼云开发者社区

云计算 云平台

iOS单元测试的那些事儿

珲少

尤雨溪向初学者推荐Vite 【为什么使用Vite】

flow

签约计划第三季

公司刚来的阿里p8,看完我构建的springboot框架,甩给我一份文档

程序员啊叶

Java 编程 程序员 架构 java面试

最新战报:十项认证,五项最佳实践

天翼云开发者社区

云计算 分布式云

敏捷开发与DevOps的对比

码语者

DevOps 敏捷

海外APP推送(下篇):海外厂商通道集成指南

极光GPTBots-极光推送

sdk 厂商通道

百问百答第48期:极客有约——可观测体系的建设路径

博睿数据

可观测性 智能运维 博睿数据 性能监测 极客有约

面试京东T5,被按在地上摩擦,鬼知道我经历了什么?

程序员啊叶

Java 编程 程序员 架构 java面试

天翼云Web应用防火墙(边缘云版)支持检测和拦截Apache Spark shell命令注入漏洞

天翼云开发者社区

Shell 防火墙

向日葵远程控制为何采用BGP服务器?自动最优路线、跨运营商高速传输

贝锐

远程控制 向日葵

在北京选择前端培训班学习大数据

小谷哥

银行业客户体验管理现状与优化策略分析

易观分析

银行

数据泄漏、删除事件频发,企业应如何构建安全防线?

京东科技开发者

公司管理 网络安全 安全 删库 程序员‘

一百五十个终极Java 经典面试题(你会多少题?)

程序员啊叶

Java 编程 程序员 架构 java面试

目标检测网络R-CNN 系列

阿炜小菜鸡

深度学习 目标检测 7月月更

@千行百业,一起乘云而上!

天翼云开发者社区

云计算 云平台

大数据培训机构有哪些值得推荐?

小谷哥

技术分享:国民远控向日葵如何通过BBR算法提升远控体验?

贝锐

技术分享 远程控制 TCP拥塞控制 向日葵 BBR

敲黑板画重点:七种常见“分布式事务”详解

程序员啊叶

Java 编程 程序员 架构 java面试

深度学习3D人体姿态估计国内外研究现状及痛点

阿炜小菜鸡

深度学习 人体姿态估计

TDSQL-C Serverless:助力初创企业实现降本增效

石云升

全球架构师峰会 ArchSummit

10 万字节Spring Boot +redis详细面试笔记(带完整目录)免费分享

程序员啊叶

Java 编程 程序员 架构 java面试

参加前端培训班学web前端技术靠谱吗

小谷哥

Redis为什么这么快?Redis的线程模型与Redis多线程

程序员啊叶

Java 编程 程序员 架构 Java 面试

什么是RPC?RPC框架dubbo的核心流程

程序员啊叶

Java 编程 程序员 架构 java面试

行业案例|指标中台如何助力银行业普惠金融可持续发展

Kyligence

大数据 普惠金融 指标中台

万字长文,浅谈企业数字化建模蓝图

产品老高

数字化 中台架构

Plato Farm有望通过Elephant Swap,进一步向外拓展生态

西柚子

使用 Amazon Textract 和 Amazon Comprehend Medical 实现无服务器化的医疗文档分析(一)_行业深度_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章