Я создаю классификатор документов, используя отсканированные документы в качестве входных данных. У меня уже есть обученная модель, но в настоящее время я занимаюсь рефакторингом кода и строю независимые блоки для лучшего обслуживания и облегчения понимания кода. Я относительно новичок в Python, поэтому, возможно, я не использую sklearn-Pipelines должным образом, так как я использую пути изображений в качестве входных данных, а не DataFrames, но я прочитал, что единственное требование состояло в том, чтобы создать свой собственный преобразователь с методами подгонки и преобразования, поэтому я пробую этосейчас.
Я хотел создать конвейер, как в sklearn. Я создал разные блоки, следуя структуре, описанной в книге «Практическое машинное обучение с Scikit-Learn и Tensor-flow». Мой первый блок - это загрузчик изображений (вход: путь к изображению, выход: тип PIL.Image), за которым последуют блок обработки изображения, блок оптического распознавания символов, блок преобразования текста и классификатор. Моя первая первая попытка заставить конвейер работать очень просто: я пытался заставить его работать только с первым блоком, но я уже столкнулся с серьезной проблемой.
Я вставляю класс ImageLoader и то, как я создал конвейер:
class ImageLoader(BaseEstimator, TransformerMixin):
'''
this class takes a path as input an return a PIL image
'''
def __init__(self, dpi_max=400, dpi_min=200):
self.dpi_max = dpi_max
self.dpi_min = dpi_min
self.path = None
def fit(self, X, y=None):
assert os.path.isfile(X), 'e: file does not exist'
self.path = X
return self
def transform(self, X, y = None):
print("processing {}...".format(self.path))
try:
if '.pdf' in self.path:
try:
with tempfile.TemporaryDirectory() as path:
image = convert_from_path(self.path, dpi=self.dpi_max, output_folder=path)[0]
except DecompressionBombError:
print('using min_dpi')
with tempfile.TemporaryDirectory() as path:
image = convert_from_path(self.path, dpi=self.dpi_min, output_folder=path)[0]
else:
image = Image.open(self.path)
except Exception as e:
print('ERROR: ', str(e))
return str(e)
if image.height > MAX_INT16 or image.width > MAX_INT16:
print('warning: this image is too big for tesseract algorithm')
return image
def fit_transform(self, X, y = None):
self.fit(X)
return self.transform()
class TestPipelineDocumentClassifier:
def test_try_pipeline(self):
image = cv2.imread('tests/data/test_Schwerbehindertenausweis.jpg')
X = 'tests/data/test_Schwerbehindertenausweis.jpg'
pipeline = Pipeline([('image_loader', ImageLoader)])
image = pipeline.fit_transform(X)
Когда я запускаю тест '' test_try_pipeline ', я получаю следующее сообщение об ошибке:
def fit_transform(self, X, y = None):
self.fit(X)
AttributeError: 'str' object has no attribute 'fit'
Проблема возникает, когда интерпретатор вводит fit_transform (self, X, y = None) моего ImageLoader, аргумент «self» содержит путь вместо ссылки на сам объект. Как это может быть? Я отладил и обнаружил, что внутри файла sklearn pipeline.py строка 393:
return last_step.fit_transform(Xt, y, **fit_params)
Xt содержит путь к изображению, а last_step является объектом типа ImageLoader, поэтому здесь все выглядит хорошо, нозатем, если я вхожу в метод, тогда я оказываюсь в ImageLoader :: fit_transform (self, X, y = 0), где аргумент 'self' содержит путь, а 'X' пусто. Почему это происходит? почему «self» не является ссылкой на объект ImageLoader, а «X» содержит путь?
Может ли тип данных быть проблемой по какой-то причине? если так, есть ли способ создать аналогичный конвейер, где выход блока является входом следующего? Более элегантно, чем просто делать:
path = 'path_to_image'
ImageProcessor().fit_transform(ImageLoader().fit_transform(path))
Большое спасибо за вашу помощь:)