Lr_find() with ImageClassifierData.from_array

(Michael) #1

I’m attempting to do the Digits Kaggle challenge as a first data set and I think I have created the ImageClassifier correctly but I’m getting an error when I come to run the learning rate finder.

The training data set is given as a csv file where each row in the csv has a label as the first column specifying what the number is and then the next 783 columns are a pixel grayscale value of an image of the handwritten digit. The images are 28 x 28 but given as a single row.

Given that I don’t have a folder of images, I am trying to use the ImageClassifierData.from_arrays. I have created 4 ndarrays: train_vals, train_Y, valid_vals and valid_Y, where train_vals is (33600, 28, 28), train_Y is (33600,), valid_vals is (8400, 28, 28) and valid_Y is (8400,).

I can create Python Images from the 28 x 28 arrays using Image.fromarray(img_data.astype(np.uint8)) where img_data is the (28, 28) ndarray and can see each of the handwritten digits.

I have defined a function to get the data:

def get_data(sz, bs):
    tfms = tfms_from_model(arch, sz, aug_tfms=transforms_basic, max_zoom=1.1)
    return ImageClassifierData.from_arrays(PATH, trn=(train_imgs, train_Y), val=(valid_imgs, valid_Y), 
                                           bs=bs, tfms=tfms)

I’m using resnet34 with sz=28 and bs=64 and I’m creating the learn object as:

learn = ConvLearner.pretrained(arch, data)

However, when I run learn.lr_find() I get the following error:

~/fastai/courses/dl1/fastai/ in transform(self, x, y)
    224     def transform(self, x, y=None):
--> 225         x = self.do_transform(x,False)
    226         return (x, self.do_transform(y,True)) if y is not None else x

~/fastai/courses/dl1/fastai/ in do_transform(self, x, is_y)
    383     def do_transform(self, x, is_y):
    384         if is_y: return scale_min(x,, cv2.INTER_NEAREST)
--> 385         else   : return scale_min(x,,   cv2.INTER_AREA   )

~/fastai/courses/dl1/fastai/ in scale_min(im, targ, interpolation)
     13     ratio = targ/min(r,c)
     14     sz = (scale_to(c, ratio, targ), scale_to(r, ratio, targ))
---> 15     return cv2.resize(im, sz, interpolation=interpolation)
     17 def zoom_cv(x,z):

error: /io/opencv/modules/imgproc/src/imgwarp.cpp:3361: error: (-215) func != 0 in function resize

I saw in another post that it might be because the resize is expecting Images so I tried converting my 28 x 28 ndarrays to Images, which forced me to change my train_vals into a list of Images but the ImageClassifierData.from_arrays won’t take a list as the dataset.

I’m very new to this so I’m not quite sure which direction to go from here.


I realized one of my problems was that resnet is expecting RGB images and the digits only have the one grayscale channel, so I was able to add an extra axis (42000, 28, 28, 1) and then broadcast_to (42000, 28, 28, 3) to turn the images into 3 channels (albeit duplicating the monochrome channel 3X). I can now run the lr_find() successfully so long as I don’t use data_augmentation or zooming, which is a bit of a bummer. I would love to know a way to get aug working with ndarray images.


After doing a fit with differential learning rates [lr/9, lr/3, lr] I managed to get it to 0.993. Its not bad but not in the the top 50 but its without any augmentation so I wonder how the results would be with data augmentation and TTA.