You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从Caffe训练集LMDB文件拆分生成验证集LMDB?

从训练集LMDB拆分生成验证集LMDB的方法

没问题!完全可以把训练集LMDB里的一部分数据拆出来做成独立的验证集LMDB,我给你一步步讲清楚怎么做:

1. 先搞定依赖库

首先确保你装了必要的工具包,用pip安装就行:

pip install lmdb opencv-python  # opencv是用来处理图像的,如果你的LMDB存的不是图像,可以只装lmdb

2. 用Python脚本拆分数据

LMDB本质是键值对数据库,我们可以读取原训练集的所有键值对,随机打乱后按比例拆分,再分别写入新的训练集和验证集LMDB。下面是现成的脚本,你直接改路径和拆分比例就能用:

import lmdb
import cv2
import numpy as np
import random

def split_lmdb(source_lmdb_path, train_lmdb_path, val_lmdb_path, split_ratio=0.9):
    # 打开源训练集LMDB
    source_env = lmdb.open(source_lmdb_path, readonly=True, lock=False)
    with source_env.begin(write=False) as txn:
        # 获取所有数据的键
        keys = [key.decode('utf-8') for key in txn.cursor().iternext(keys=True, values=False)]
        # 随机打乱键的顺序,避免验证集是连续的子集
        random.shuffle(keys)
        # 计算拆分点,比如9:1的话,90%留作训练,10%作为验证
        split_idx = int(len(keys) * split_ratio)
        train_keys = keys[:split_idx]
        val_keys = keys[split_idx:]

    # 写入新的训练集LMDB(建议保留原训练集,所以用新路径)
    train_env = lmdb.open(train_lmdb_path, map_size=1099511627776)  # map_size设成1TB足够大部分数据集
    with train_env.begin(write=True) as txn:
        with source_env.begin(write=False) as source_txn:
            for key in train_keys:
                value = source_txn.get(key.encode('utf-8'))
                txn.put(key.encode('utf-8'), value)
    train_env.close()

    # 写入验证集LMDB,也就是你需要的val_lmdb
    val_env = lmdb.open(val_lmdb_path, map_size=1099511627776)
    with val_env.begin(write=True) as txn:
        with source_env.begin(write=False) as source_txn:
            for key in val_keys:
                value = source_txn.get(key.encode('utf-8'))
                txn.put(key.encode('utf-8'), value)
    val_env.close()
    source_env.close()

if __name__ == '__main__':
    # 替换成你自己的路径
    source_path = 'train_lmdb'  # 原训练集LMDB路径
    new_train_path = 'new_train_lmdb'  # 拆分后的新训练集路径(不想改原训练集就用这个)
    val_path = 'val_lmdb'  # 要生成的验证集路径
    split_lmdb(source_path, new_train_path, val_path, split_ratio=0.9)  # 这里可以改拆分比例

3. 几个要注意的点

  • map_size别太小map_size是LMDB的最大存储空间,一定要设得比你的数据集总大小大,我上面设的1TB(1099511627776)基本能覆盖大部分图像数据集,如果你的数据特别大,可以再调大。
  • 一定要打乱顺序:别直接拿最后10%当验证集,这样分布可能和训练集不一致,验证结果不准,随机打乱才靠谱。
  • 保留原数据:建议不要直接覆盖原训练集LMDB,生成新的训练集和验证集,原数据留着备用总没错。
  • 非图像数据也能用:如果你的LMDB存的不是图像,把脚本里和cv2相关的代码删掉就行,直接处理键值对就OK。

4. 验证拆分结果

拆分完可以用下面的小脚本检查一下两个LMDB的内容是否正常:

def check_lmdb(lmdb_path):
    env = lmdb.open(lmdb_path, readonly=True, lock=False)
    with env.begin(write=False) as txn:
        count = txn.stat()['entries']
        print(f"{lmdb_path} 里有 {count} 条数据")
        # 读第一条数据看看
        cursor = txn.cursor()
        cursor.first()
        key, value = cursor.item()
        print(f"第一条数据的键:{key.decode('utf-8')}")
        # 如果是图像的话,解码看看形状
        img = cv2.imdecode(np.frombuffer(value, np.uint8), cv2.IMREAD_COLOR)
        if img is not None:
            print(f"图像形状:{img.shape}")
    env.close()

check_lmdb('new_train_lmdb')
check_lmdb('val_lmdb')

跑完脚本后,你要的val_lmdb/data.mdbval_lmdb/lock.mdb就生成好了~

内容的提问来源于stack exchange,提问作者8-Bit Borges

火山引擎 最新活动