查找相似文件

Finding Similar Document

我正在从事一个项目,在该项目中,我处理并存储了带有标签类别的单页医疗报告的文档。用户将输入一个文档,我必须对它属于哪个类别进行分类。

我已将所有文档转换为灰度图像格式并存储以供比较。

我有一个包含以下数据的图像数据集,

我打算用这两种方法,

我对图像处理领域知之甚少。上述机制对我来说是否可靠?

我检查了 SO,发现了几个相同的问题,但他们有一个非常不同的问题和期望的结果。 This question 看起来与我的情况相似,但它非常通用,我不确定它是否适用于我的情况。

Link to sample reports

我会推荐一些东西:

基于文本的比较:

OCR 文档并使用 Google 的 Tesseract 提取文本特征,这是目前最好的开源 OCR 包之一。还有一个名为 PyTesseract 的 Python 包装器。您可能需要调整图像的分辨率才能使 OCR 达到您满意的效果 - 这需要反复试验。

提取单词后,一种普遍接受的方法是计算 TF-IDF(词频 - 逆文档频率),然后使用任何基于距离的方法(余弦相似度是一种常见的方法)进行比较哪些文档彼此 "similar"(更接近)。

基于图像的比较

如果您已经将图像作为矢量,则应用基于距离的度量来计算相似性。通常 L1 或 L2 范数都可以。 paper 表明曼哈顿(L1 范数)可能更适合自然图像。您可以从那开始并尝试其他基于距离的措施

基于集成文本和图像的比较

运行 这两种方法,然后在这两种方法之间取一些平均值以获得彼此相似的文档。

例如

基于文本的方法可能会将 DocB 和 DocC 列为最接近 DocA 的两个文档,距离分别为 10 和 20 个单位。

基于图像的方法可能会将 DocC 和 DocB 分别列为最接近距离 5 和距离 20 的两个。

然后你可以平均这两个距离。 DocB 将是 (10+20)/2 = 15,DocC 将是 (20+5)/2 = 12.5 个单位,与 DocA 相距。因此,在集成方法中,您会将 DocC 视为更接近 A 而不是 B。

与从文本中测量文档相比,从图像中测量文档的相似性更复杂,原因有二。

  1. 图像在亮度、文本上下文、图表或符号方面可能具有相似性。
  2. 与文本信息相比,从文档包含的图像中找到文档的表示通常更难。

解决方案

我的解决方案是使用机器学习来查找文档的表示,并使用该表示对文档进行分类。 这里我将我提出的解决方案给 Keras 实现。

网络类型

我建议使用卷积层进行特征提取,然后使用循环层进行序列分类。我选择 keras 是因为我很熟悉,它可以简单地 API 定义一个由卷积层和循环层组合而成的网络。但是代码可以方便的改成Pytorch、Tensorflow等其他库

图像预处理

有很多方法可以为神经网络预处理文档图像。我在做假设。

  • 图像包含水平文本而不是垂直文本。
  • 文档图片大小是固定的。如果图像大小不固定,可以使用 opencv's resize 方法调整大小。

垂直拆分图像,以便将行作为序列馈送(如果拆分线可以在空行上进行,则效率更高)。我将使用 Numpy 对单个文档进行展示。在下面的实现中,我假设单个文档的图像形状是 (100, 100, 3)。 首先,让我们定义 image_shape 文档图像的形状为

import numpy as np
image_shape = (100, 100, 3)
split_size = 25 # this should be factor of the image_shape[0]
doc_images = [] #
doc_image = np.zeros(image_shape)

splitted_images = np.split(doc_image,[split_size], axis=0)
doc_images.extend(splitted_images)
doc_images = np.array(doc_images)

网络实现

Keras 有 ConvLSTM2D 层来处理序列图像。网络的输入是通过拆分文档图像生成的图像序列列表。

from keras.models import Sequential
from keras.layers import ConvLSTM2D, Dense, Flatten
num_of_classes = 10
model = Sequential()

model.add(ConvLSTM2D(32,(3, 3),input_shape=(None, split_size, image_shape[1],image_shape[2]),
        padding='same',
        return_sequences=True))
model.add(ConvLSTM2D(32,(3, 3),padding='same',return_sequences=True))
model.add(ConvLSTM2D(32,(3, 3),padding='same',return_sequences=False))
model.add(Flatten())
model.add(Dense(1024, activation="relu"))
model.add(Dense(num_classes, activation="softmax"))

理想情况下,该模型会起作用,因为该模型可能会从图像中学习文档的层次表示(字符、单词、句子、上下文、符号)。

样本文档差异很大,无法在图像级别(直方图,np_avg)进行比较。

报告的内容是多个数字(最小值、最大值、推荐值)或类别结果(Negative/Positive)。

对于每种类型的报告,您都必须进行预处理。

如果文档来源是数字的(不是扫描的),您可以提取和比较字段、行。每行分开。

  • 提取字段或行的图像部分并与 NN 进行比较
  • 文本提取和比较值 (OCR)

如果扫描文档,您必须在提取之前处理图像旋转、质量和伪影。

每种类型的报告都有其自身的问题。选择一种包含多个样本的报告作为开始。

由于您处理的是数字,因此仅提取文本和数字即可获得良好的结果。如果报告说值为 0.2 并且容忍范围在 0.1 和 0.3 之间,则 NN 不是该工具。你必须比较数字。

NN 不是最好的工具,至少不是比较值。也许是提取过程的一部分。

解决步骤

  • 报告自动分类
  • 为每种类型的报告标记字段数据
  • 对于每种类型的报告自动提取值
  • 对于每种类型的报告,根据业务规则解释值