跨模态神经搜索实践VCED-Jina学习

1. Jina 是什么

简单来说 Jina 可以帮助你快速把非结构化数据例如图像,文档视频等,转换为向量数据。并结合 Jina 的其他组件设计,帮助你快速的把向量数据利用起来,实现多模态的数据搜索。

2. Jina 的三个基本概念

Document、Executor 和 Flow 是 Jina 的三个基本概念。

  • Document 是基本的数据类型,它的作用就是可以将非结构化数据与向量数据之间进行映射,具体细节会在 DocArray 一章中详细阐述。
  • Executor 可以理解为一个 Python 类,代表了 Jina 中的算法单元,比如把图像编码成向量、对结果进行排序等算法等都可以用
  • Executor 来表述。 Flow 可以将多个 Executor 连接起来,将他们协调成流水线(pipeline)。

3. Document

Document 是基本的数据类型,与之相关的几个概念统一用DocArray来称呼。DocArray 由三个简单的概念组成:

  • Document:一种表示嵌套非结构化数据的数据结构,是 DocArray 的基本数据类型。无论是处理文本、图像、视频、音频、3D、表格或它们的嵌套或组合,都可以用 Document 来表示,从而使得各类数据的结构都非常规整,方便后续处理
  • DocumentArray:用于高效访问、处理和理解多个文档的容器,可以保存多个 Document 的列表
  • Dataclass:用于直观表示多模式数据的高级API
    以下是通过DocArray表示不同数据类型的示例

3.1 Text

3.1.1 导入文本

在 DocArray 中表示文本非常简单

from docarray import Document

Document(text='hello, world.')

如果文本数据较大,或者来自 URI,可以先定义 uri,然后再将文本加载到文档中:

from docarray import Document

d = Document(uri='https://www.w3.org/History/19921103-hypertext/hypertext/README.html')
d.load_uri_to_text()

d.summary()

也可以使用不同语言的字符:

from docarray import Document

d = Document(text='	नमस्ते दुनिया!	你好世界!こんにちは世界!	Привет мир!')

3.1.2 分割长文档

我们经常会遇到处理长文本的情况,此时可能会有分割长文本的需求,可以通过chunks来执行此操作。

from docarray import Document

d = Document(text='	नमस्ते दुनिया!	你好世界!こんにちは世界!	Привет мир!')

d.chunks.extend([Document(text=c) for c in d.text.split('!')])

d.summary()
 
    └─ chunks
          ├─ 
          ├─ 
          ├─ 
          ├─ 
          └─ 

如上所示,在原始文档下创建了五个子文档,并将它们存储在原始文档的 .chunk 下。

3.1.3 将文本转换为 ndarray

有时需要在进一步计算之前将文本编码为 numpy.ndarray。在 Document 和 DocumentArray 中提供了一些函数,可以完成此操作。

例如,我们有一个包含三个文档的文档数组:

from docarray import DocumentArray, Document

da = DocumentArray(
    [
        Document(text='hello world'),
        Document(text='goodbye world'),
        Document(text='hello goodbye'),
    ]
)

要获取vocabulary,可以使用:

vocab = da.get_vocabulary()
{'hello': 2, 'world': 3, 'goodbye': 4}

这里词汇索引从2开始,是因为0 表示padding,1 表示unknow。 可以进一步使用此词汇将 .text 字段转换为 .tensor:

for d in da:
    d.convert_text_to_tensor(vocab)
    print(d.tensor)
[2 3]
[4 3]
[2 4]

另外,可以通过max_length参数调整tensor的长度:

from docarray import Document, DocumentArray

da = DocumentArray(
    [
        Document(text='a short phrase'),
        Document(text='word'),
        Document(text='this is a much longer sentence'),
    ]
)
vocab = da.get_vocabulary()

for d in da:
    d.convert_text_to_tensor(vocab, max_length=10)
    print(d.tensor)
[0 0 0 0 0 0 0 2 3 4]
[0 0 0 0 0 0 0 0 0 5]
[ 0  0  0  0  6  7  2  8  9 10]

还可以使用 DocumentArray 的 .tensors 在ndarray 中一次性获取所有张量。

[[ 0  0  0  0  0  0  0  2  3  4]
 [ 0  0  0  0  0  0  0  0  0  5]
 [ 0  0  0  0  6  7  2  8  9 10]]

3.1.4 将 ndarray 转换回文本

还可以根据给定的vocabulary将ndarray 转换回文本。

from docarray import Document, DocumentArray

da = DocumentArray(
    [
        Document(text='a short phrase'),
        Document(text='word'),
        Document(text='this is a much longer sentence'),
    ]
)
vocab = da.get_vocabulary()

# encoding
for d in da:
    d.convert_text_to_tensor(vocab, max_length=10)

# decoding
for d in da:
    d.convert_tensor_to_text(vocab)
    print(d.text)
a short phrase
word
this is a much longer sentence

3.1.5 使用特征哈希进行简单的文本匹配

在《傲慢与偏见》中搜索“she entered the room”:

from docarray import Document, DocumentArray

d = Document(uri='https://www.gutenberg.org/files/1342/1342-0.txt').load_uri_to_text()
da = DocumentArray(Document(text=s.strip()) for s in d.text.split('\n') if s.strip())
da.apply(lambda d: d.embed_feature_hashing())

q = (
    Document(text='she entered the room')
    .embed_feature_hashing()
    .match(da, limit=5, exclude_self=True, metric='jaccard', use_scipy=True)
)

print(q.matches[:, ('text', 'scores__jaccard')])
[['staircase, than she entered the breakfast-room, and congratulated', 
'of the room.', 
'She entered the room with an air more than usually ungracious,', 
'entered the breakfast-room, where Mrs. Bennet was alone, than she', 
'those in the room.'], 
[{'value': 0.6, 'ref_id': 'f47f7448709811ec960a1e008a366d49'}, 
{'value': 0.6666666666666666, 'ref_id': 'f47f7448709811ec960a1e008a366d49'}, 
{'value': 0.6666666666666666, 'ref_id': 'f47f7448709811ec960a1e008a366d49'}, 
{'value': 0.6666666666666666, 'ref_id': 'f47f7448709811ec960a1e008a366d49'}, 
{'value': 0.7142857142857143, 'ref_id': 'f47f7448709811ec960a1e008a366d49'}]]

未完待续。。。

你可能感兴趣的:(跨模态神经搜索实践,jina,python)