LMDB内存映射型数据库

一、LMDB简要介绍

LMDB(Lightning Memory-Mapped Database),是一个读存速度很快的内存映射型数据库,其属于Key-Value数据库,而不是关系型数据库( 如MySQL ),提供数据管理功能,可以将各种各样的原始数据转换为统一的Key-Value存储,用在深度学习上的情况是可以将神经网络的大型数据集存储在 LMDB 中,LMDB不仅可以用来存放训练和测试用的数据集,还可以存放神经网络提取出的特征数据(要求这些数据结构简单、数据之间没有什么关联)

二、LMDB原理

LMDB是基于内存映射的,这意味着它返回指向键和值的内存地址的指针,而不需要像大多数其他数据库那样复制内存中的任何内容,因此它读存速度非常快。
LMDB的文件结构是一个文件夹,里面是一个数据文件和一个锁文件,数据随意复制,随意传输。它的访问简单,不需要单独的数据管理进程。只要在访问代码里引用LMDB库,访问时给文件路径即可。
用LMDB数据库来存放图像数据,而不是直接读取原始图像数据的原因:

  1. 数据类型多种多样,比如:二进制文件、文本文件、编码后的图像文件jpeg、png等,不可能用一套代码实现所有类型的输入数据读取,因此通过LMDB数据库,转换为统一数据格式可以简化数据读取层的实现。
  2. lmdb具有极高的存取速度,大大减少了系统访问大量小文件时的磁盘IO的时间开销。LMDB将整个数据集都放在一个文件里,避免了文件系统寻址的开销,你的存储介质有多快,就能访问多快,不会因为文件多而导致时间长。LMDB使用了内存映射的方式访问文件,这使得文件内寻址的开销大幅度降低。

三、实现流程

1. 创建 lmdb 环境
2. 建立事务
3. 进行增删改查,遍历等操作
4. 提交事务
5. 关闭lmdb 环境

例如:
import lmdb
# 创建 lmdb 环境
env = lmdb.open(lmdb_path, map_size=1099511627776)
#建立事务
txn = env.begin(write=True)
# 增删改查
txn.put(str(1).encode(), "Alice".encode())
txn.put(str(2).encode(), "Bob".encode())
txn.delete(str(1).encode())
for key, value in txn.cursor():
    print(key, value)
# 提交事务
txn.commit()
# 关闭lmdb 环境
env.close()

注意:需要把str类等数据通过encode()转换为bytes格式
下面通过例子查看图片数据存储和读取的流程:

  1. 将图片和对应的文本标签存放到lmdb数据库:
import lmdb

image_path = './cat.jpg'
label = 'cat'

env = lmdb.open('lmdb_dir')
cache = {}  # 存储键值对

with open(image_path, 'rb') as f:
    # 读取图像文件的二进制格式数据
    image_bin = f.read()

# 用两个键值对表示一个数据样本
cache['image_000'] = image_bin
cache['label_000'] = label

with env.begin(write=True) as txn:
    for k, v in cache.items():
        if isinstance(v, bytes):
            # 图片类型为bytes
            txn.put(k.encode(), v)
        else:
            # 标签类型为str, 转为bytes
            txn.put(k.encode(), v.encode())  # 编码
env.close()

这里需要获取图像文件的二进制格式数据,然后用两个键值对保存一个数据样本,即分开保存图片和其标签,然后分别将图像和标签写入到lmdb数据库中,和上面例子一样都需要将键值转换为 bytes 格式

  1. 从lmdb数据库中读取图片数据:
import cv2
import lmdb
import numpy as np

env = lmdb.open('lmdb_dir')
with env.begin(write=False) as txn:
    # 获取图像数据
    image_bin = txn.get('image_000'.encode())
    label = txn.get('label_000'.encode()).decode()  # 解码

    # 将二进制文件转为十进制文件(一维数组)
    image_buf = np.frombuffer(image_bin, dtype=np.uint8)
    # 将数据转换(解码)成图像格式
    # cv2.IMREAD_GRAYSCALE为灰度图,cv2.IMREAD_COLOR为彩色图
    img = cv2.imdecode(image_buf, cv2.IMREAD_COLOR)
    cv2.imshow('image', img)
    cv2.waitKey(0)

先通过 lmdb.open() 获取之前创建的lmdb数据库,这里通过键得到图片和其标签,因为写入数据库之前进行了编码,所以这里需要先解码。

四、总结

LMDB是内存映射型数据库,基于K-V结构,读存速度非常快,适用于神经网络大型数据集。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值