Отправка данных cv.imread () в модель Keras - PullRequest
1 голос
/ 18 апреля 2020

У меня проблемы с попыткой выяснить, как отправить данные из cv.imread () в мою модель машинного обучения.

Из моей функции чтения изображений я получаю список numpy массивов, которые содержат изображения с размером (256, 256, 3).

# image reading
res_img = []
for i in files:
    img = cv2.imread(os.path.join("temp", i))
    res = cv2.resize(img, (256, 256))
    res_img.append(res)
return res_img

Затем он сохраняется в кадре данных и отправляется в модель. Тем не менее, определяется, что датафрейм имеет размерность (56, 1), где 56 - длина моих данных, а 1 - потому что каждый массив numpy определяется как 1 объект.

# train model
model = create_model(trainX)
model_history = model.fit(trainX, trainY, validation_data=(testX, testY), epochs=..., batch_size=...)
# create model
def create_model(data):
    model = Sequential()
    model.add(Conv2D(32, kernel_size=4, activation='relu', input_shape=(256, 256, 3)))
    ...
    return model

Однако это возвращает

ValueError: Error when checking input: expected conv2d_input to have 4 dimensions, but got array with shape (56, 1)

Другая вещь, которую я пытался, состояла в том, чтобы объединить все массивы numpy в данных в большой массив numpy, который имел правильные размеры

trainX_arr = []
trainX = trainX.to_numpy()
for i in trainX:
    trainX_arr.append(i)
    trainX_arr = np.asarray(trainX_arr)

Это дает правильную форму:

print(trainX_arr.shape)
# (56, 256, 256, 3)

Однако при отправке в модель возвращается

ValueError: No data provided for "conv2d_input". Need data for each key in: ['conv2d_input']

Я предполагаю, что входные данные не являются фреймом данных. Наконец, я попытался на первом шаге объединить массивы numpy, а затем сохранить их в кадре данных, например,

res_img = []
for i in files:
    img = cv2.imread(os.path.join("temp", i))
    res = cv2.resize(img, (256, 256))
    res_img.append(res)
img_arr = []
for i in res_img:
    img_arr.append(i)
    img_arr = np.asarray(img_arr)
return img_arr

Однако при попытке вставить его в кадр данных:

df.insert(0, "x", img_arr)

Возвращает

ValueError: Wrong number of dimensions. values.ndim != ndim [4 != 2]

Я полагаю, это потому, что кадр данных не может содержать многомерный массив, но это возвращает меня к тому, с чего я начал. Я действительно смущен тем, что я должен делать, чтобы заставить это работать, и любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 20 апреля 2020

Мне удалось заставить его работать, где мой второй метод, который объединил массивы numpy в большой массив с допустимыми измерениями, смог успешно обучить модель. Я не уверен, почему это не сработало ранее, но вот мой код, который работает:

Определил функцию (произвольно называемую numpyfy) для выполнения объединения этого массива

import os

import cv2
import numpy as np
import pandas as pd
from keras.layers import Conv2D, Dense, Flatten, MaxPooling2D
from keras.engine.input_layer import Input
from keras.models import Model
from sklearn.model_selection import train_test_split


# download images
def process_link(link_list):
    counter = 0
    for i in link_list:
        if i.find("jpg") != -1:
            ext = ".jpg"
        elif i.find("png") != -1:
            ext = ".png"
        f = open(os.path.join("temp", str(counter) + ext), "wb")
        f.write(requests.get(i).content)
        f.close()
        counter += 1
    files = os.listdir("temp") # images stored in temp directory
    res_img = []
    for i in files:
        img = cv2.imread(os.path.join("temp", i))
        res = cv2.resize(img, (256, 256))
        res_img.append(res)
    return res_img

# process data
def process_data():
    # link_list and y are a list of: links to images, and data labels, respectively
    df = pd.DataFrame()
    df.insert(0, "Y", y])
    df.insert(0, "img", process_link(link_list))
    (train, test) = train_test_split(clean_df, test_size=0.25, random_state=42)
    return (train, test)

# numpy array combining
def numpyfy(df):
    arr = []
    df_numpy = df.to_numpy()
    print(df_numpy[:2])
    for i in df_numpy:
        arr.append(i)
    arr = np.asarray(arr)
    #print(arr.shape), returns 4 dimensional array
    return arr

# Deep learning model, changed to use the Functional API
def create_model():
    input1 = Input(shape=(256, 256, 3))
    conv1 = Conv2D(32, (3, 3), input_shape=(3, 256, 256), activation="relu")(inpu1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
    conv2 = Conv2D(32, (3, 3), activation="relu")(pool1)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
    flat1 = Flatten()(pool2)
    dense1 = Dense(16, activation="relu")(flat1)
    dense2 = Dense(1, activation="sigmoid")(dense1)
    model = Model(inputs=input1, outputs=dense2)
    model.compile(loss='mse', optimizer='adadelta', metrics=['mse', 'mae'])
    return model

# train model
def train_model():
    (train, test) = process_data() #Returns 2 dataframes (train, test)
    train_img, test_img = numpyfy(train["img"]), numpyfy(test["img"])
    model = create_model()
    model.fit(train_img, train["Y"], validation_data=(test_img, test["Y"]),
            epochs=epochs, batch_size=batch_size)

В конце я не уверен, что я сделал по-другому, что не выдало ошибку, но это работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...