Creating your own dataset from Google Images

Get a list of URLs

Now you must run some Javascript code in your browser which will save the URLs of all the images you want for you dataset.

Press CtrlShiftJ in Windows/Linux and CmdOptJ in Mac, and a small window the javascript 'Console' will appear. That is where you will paste the JavaScript commands.

You will need to get the urls of each of the images. You can do this by running the following commands:

urls = Array.from(document.querySelectorAll('.rg_di .rg_meta')).map(el=>JSON.parse(el.textContent).ou);
window.open('data:text/csv;charset=utf-8,' + escape(urls.join('\n')));

Create directory and upload urls file into your server

In [67]:
from fastai import *
from fastai.vision import *
In [ ]:
# folder = 'other'
# file = f'{folder}.csv'

# path = Path('/home/akomma/.fastai/data/cuisine/')
# dest = path/'images'/folder
# dest.mkdir(parents=True, exist_ok=True)

# download_images(path/file, dest, max_pics=200)
In [ ]:
# !echo {dest}
# ! ls {dest} | wc -l

Download images

In [68]:
path = Path('/home/akomma/.fastai/data/cuisine/images/')

# classes = ['indian','mexican','japanese', 'thai', 'vietnamese', 'chinese', 'american', 'french', 'italian', 'other']
# len(classes)
In [69]:
# If you have problems download, try with `max_workers=0` to see exceptions:
# download_images(path/file, dest, max_pics=20, max_workers=0)

Then we can remove any images that can't be opened:

In [14]:
# for c in classes:
#     print(c)
#     verify_images(path/'images'/c, delete=True)
In [43]:
path
Out[43]:
PosixPath('/home/akomma/.fastai/data/cuisine/images')
In [44]:
list(path.glob('indian/*.png'))[0:5]
Out[44]:
[PosixPath('/home/akomma/.fastai/data/cuisine/images/indian/00000029.png'),
 PosixPath('/home/akomma/.fastai/data/cuisine/images/indian/00000165.png'),
 PosixPath('/home/akomma/.fastai/data/cuisine/images/indian/00000018.png'),
 PosixPath('/home/akomma/.fastai/data/cuisine/images/indian/00000117.png'),
 PosixPath('/home/akomma/.fastai/data/cuisine/images/indian/00000037.png')]
In [ ]:
# import PIL
# for fn in path.glob('images/*/*.png'):
#     im = PIL.Image.open(fn)
#     if im.mode != 'RGB': im.convert('RGB').save(fn)

View data

In [70]:
np.random.seed(42)
data = ImageDataBunch.from_folder(path, train="images", valid_pct=0.2, ds_tfms=get_transforms(flip_vert=True),
        size=299, bs = 16, num_workers=4).normalize(imagenet_stats)

Good! Let's take a look at some of our pictures then.

In [71]:
data.classes
Out[71]:
['mexican', 'indian', 'japanese', 'italian', 'chinese']
In [72]:
data.show_batch(rows=3, figsize=(7,8))
In [74]:
data.classes, data.c, len(data.train_ds), len(data.valid_ds)
Out[74]:
(['mexican', 'indian', 'japanese', 'italian', 'chinese'], 5, 760, 189)

Train model

In [75]:
learn = create_cnn(data, models.resnet50, metrics=[error_rate, accuracy])
In [76]:
learn.fit_one_cycle(4)
Total time: 02:25
epoch  train_loss  valid_loss  error_rate  accuracy
1      1.696026    1.327369    0.455026    0.544974  (00:41)
2      1.448649    1.060079    0.375661    0.624339  (00:33)
3      1.195122    0.967517    0.359788    0.640212  (00:36)
4      0.991352    0.944127    0.343915    0.656085  (00:34)

In [77]:
learn.save('stage-1-res50')
In [78]:
learn.unfreeze()
In [79]:
learn.lr_find()
LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.
In [80]:
learn.recorder.plot()
In [81]:
learn.fit_one_cycle(2, max_lr=slice(1e-5,3e-5))
Total time: 01:24
epoch  train_loss  valid_loss  error_rate  accuracy
1      0.879890    0.913639    0.359788    0.640212  (00:41)
2      0.824703    0.898454    0.354497    0.645503  (00:42)

In [82]:
learn.save('stage-2-res50')
In [83]:
learn.fit_one_cycle(10, max_lr=slice(3e-5))
Total time: 06:59
epoch  train_loss  valid_loss  error_rate  accuracy
1      0.727504    0.887410    0.333333    0.666667  (00:40)
2      0.752659    0.891064    0.328042    0.671958  (00:40)
3      0.706726    0.880307    0.328042    0.671958  (00:41)
4      0.699234    0.866236    0.312169    0.687831  (00:41)
5      0.633498    0.866681    0.301587    0.698413  (00:41)
6      0.643695    0.853697    0.296296    0.703704  (00:41)
7      0.591022    0.867654    0.306878    0.693122  (00:42)
8      0.585642    0.862425    0.301587    0.698413  (00:43)
9      0.570796    0.852754    0.275132    0.724868  (00:42)
10     0.555791    0.858157    0.285714    0.714286  (00:42)

In [84]:
learn.save('stage-3-res50')
In [85]:
learn.recorder.plot_losses()

Interpretation

In [ ]:
# learn.load('stage-3-res50');
In [86]:
interp = ClassificationInterpretation.from_learner(learn)
In [87]:
interp.plot_confusion_matrix()
In [88]:
interp.plot_top_losses(9, figsize=(15,11))