图像分类训练触发UnidentifiedImageError:无法识别图像文件
Keras图像分类器训练报错解决指南
问题详情
我开发了一个基于Keras的图像分类器,代码如下:
from keras.preprocessing.image import ImageDataGenerator from keras.preprocessing import image from keras.optimizers import RMSprop import matplotlib as plt import tensorflow as tf import numpy as np import cv2 import os import keras.utils as image from matplotlib import pyplot as plt train = ImageDataGenerator(rescale = 1/255) validation = ImageDataGenerator(rescale = 1/255) train_dataset = train.flow_from_directory('family/train/', target_size = (500,500), batch_size = 3 ,class_mode = 'binary') validation_dataset = validation.flow_from_directory('family/validate/', target_size = (500,500), batch_size = 3 ,class_mode = 'binary') train_dataset.class_indices train_dataset.classes from tensorflow.keras import layers , models model=models.Sequential() model.add(layers.Conv2D(16,(3,3),activation='relu', input_shape=(500,500,3))) model.add(layers.MaxPooling2D((2,2))) model.add(layers.Conv2D(32,(3,3),activation = 'relu')) model.add(layers.MaxPooling2D((2,2))) model.add(layers.Conv2D(64,(3,3),activation = 'relu')) model.add(layers.Flatten()) model.add(layers.Dense(512, activation = 'relu')) model.add(layers.Dense(1, activation = 'sigmoid')) model.compile(loss = 'binary_crossentropy',optimizer = RMSprop(learning_rate=0.001), metrics = ['accuracy']) model.fit(train_dataset, steps_per_epoch = 3, epochs=30,validation_data=validation_dataset) img = image.load_img("family/testing//test1.jpg") plt.imshow(img) plt.show() X= image.img_to_array(img) X=np.expand_dims(X,axis=0) images = np.vstack([X]) val=model.predict(images) if val == 1 : print(" one") if val == 2 : print(" two")
执行后先输出:
Found 10 images belonging to 3 classes.
Found 10 images belonging to 3 classes.
但运行到model.fit训练模型时触发报错,报错栈如下:
--------------------------------------------------------------------------- UnidentifiedImageError Traceback (most recent call last) /var/folders/5m/ybwkn1396vd8_rzf_7gpcv9c0000gq/T/ipykernel_7121/2750052911.py in <module> 35 36 model.compile(loss = 'binary_crossentropy',optimizer = RMSprop(learning_rate=0.001), metrics = ['accuracy']) ---> 37 model.fit(train_dataset, steps_per_epoch = 3, epochs=30,validation_data=validation_dataset) 38 39 ~/opt/anaconda3/lib/python3.9/site-packages/keras/utils/traceback_utils.py in error_handler(*args, **kwargs) 68 # To get the full stack trace, call: 69 # `tf.debugging.disable_traceback_filtering()` ---> 70 raise e.with_traceback(filtered_tb) from None 71 finally: 72 del filtered_tb ~/opt/anaconda3/lib/python3.9/site-packages/PIL/Image.py in open(fp, mode, formats) 3145 for message in accept_warnings: 3146 warnings.warn(message) -> 3147 raise UnidentifiedImageError( 3148 "cannot identify image file %r" % (filename if filename else fp) 3149 ) UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x1623fb680>
我的文件夹结构为family目录下包含train和validate子目录,不清楚报错原因。
报错原因
这个UnidentifiedImageError的核心原因是:数据集目录中存在无法被PIL库识别的文件,具体可能是以下情况之一:
- 目录里有非图像文件(比如系统自动生成的
.DS_Store、Thumbs.db隐藏文件,或者文本、缓存文件) - 部分图像文件损坏、不完整,或者格式不在PIL支持范围内
- 文件扩展名与实际格式不匹配(比如把PNG文件改成了JPG后缀)
另外注意到数据集有3个类别,但当前模型用了二分类的配置(class_mode='binary'、binary_crossentropy损失、sigmoid输出层),这属于配置错误,后续也需要修正,但不是当前报错的直接原因。
解决步骤
1. 清理数据集目录
- 检查
family/train和family/validate下的所有文件,删除非图像类型的文件 - 手动验证每个图像文件能否正常打开,删除损坏的图像
2. 在数据生成器中跳过损坏文件
如果使用的是较新版本的Keras,可以在flow_from_directory中添加skip_broken_images=True参数,自动跳过无法识别的图像:
train = ImageDataGenerator(rescale=1/255) train_dataset = train.flow_from_directory( 'family/train/', target_size=(500,500), batch_size=3, class_mode='binary', skip_broken_images=True ) validation_dataset = validation.flow_from_directory( 'family/validate/', target_size=(500,500), batch_size=3, class_mode='binary', skip_broken_images=True )
3. 修正多分类模型配置
因为你的数据集有3个类别,当前二分类配置是错误的,需要调整为多分类模式:
# 修正数据生成器的类别模式 train_dataset = train.flow_from_directory( 'family/train/', target_size=(500,500), batch_size=3, class_mode='categorical' ) validation_dataset = validation.flow_from_directory( 'family/validate/', target_size=(500,500), batch_size=3, class_mode='categorical' ) # 修正模型输出层 model.add(layers.Dense(3, activation='softmax')) # 修正编译参数 model.compile( loss='categorical_crossentropy', optimizer=RMSprop(learning_rate=0.001), metrics=['accuracy'] ) # 修正预测逻辑 val = model.predict(images) predicted_class_idx = np.argmax(val) # 获取类别名称映射 class_names = list(train_dataset.class_indices.keys()) print(f"预测类别: {class_names[predicted_class_idx]}")
内容的提问来源于stack exchange,提问作者Ashraf Abazeed
相关产品推荐
相关产品推荐

