Skip to content

Commit

Permalink
added python demo and 5 alphabet background sets
Browse files Browse the repository at this point in the history
  • Loading branch information
brendenlake committed Oct 21, 2015
1 parent edbf998 commit 32aee47
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 15 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
matlab_to_python
python/images_background
python/images_background_small1
python/images_background_small2
python/images_evaluation
python/one-shot-classification/run**
59 changes: 44 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,52 @@
# omniglot
Omniglot data set for one-shot character recognition.
# Omniglot data set for one-shot learning

This dataset contains 1623 handwritten characters from 50 different alphabets.
Each of the 1623 characters was drawn online via Amazon's Mechanical Turk by 20 different people.
Each image is paired with stroke data (formatted as [x,y,time in milliseconds]).
This dataset contains 1623 different handwritten characters from 50 different alphabets.
Each of the 1623 characters was drawn online via Amazon's Mechanical Turk by 20 different people.
Each image is paired with stroke data, a sequences of [x,y,t] coordinates with time (t) in milliseconds. Stroke data is available in MATLAB files only.

MATLAB:
Learn about the structure of the data set by running 'demo.m'.
There are two main data files: 'data_background.mat' (30 alphabets) and 'data_evaluation.mat' (20 alphabets). The one-shot learning results we report involve only characters from 'data_evaluation', while 'data_background' can be used by algorithms to learn general knowledge about characters.
### CONTENTS
The Omniglot data set contains 50 alphabets total.

To compare with the one-shot classification results in our paper, use 'demo_classification.m' in the 'one-shot-classification' folder to run the baseline Modified Hausdorff Distance.
Here is the split:
background : 30 alphabets
evaluation : 20 alphabets

PYTHON:
Coming soon
To compare with the results in our paper, only the background set should be used by algorithms to learn general knowledge about characters (e.g., hyper-parameter inference or feature learning). One-shot learning results are reported using alphabets from the evaluation set.

To cite this data set, please cite the following paper:
For a smaller and more challenging background set, the sets "background small 1" and "background small 2" contain just 5 alphabets each.


### MATLAB

Learn about the structure of the data set by running the script 'demo.m'.

Key data files:
data_background.mat
data_evaluation.mat
data_background_small1.mat
data_background_small2.mat

To compare with the one-shot classification results in our paper, run 'demo_classification.m' in the 'one-shot-classification' folder to demo a baseline model using Modified Hausdorff Distance.


### PYTHON

Python 2.7.*
Requires scipy and numpy

Key data files:
images_background.zip
images_evaluation.zip
images_background_small1.zip
images_background_small2.zip

To compare with the one-shot classification results in our paper, enter the 'one-shot-classification' directory and unzip 'all_runs.zip' and place all the folders 'run01',...,'run20' in the current directory. Run 'demo_classification.py' to demo a baseline model using Modified Hausdorff Distance.


### Citing this data set
Please cite the following paper:

Human-level concept learning through probabilistic program induction
By Brenden Lake, Ruslan Salakhutdinov, and Joshua Tenenbaum
Email: brenden at-sign nyu dot edu
By Brenden Lake, Ruslan Salakhutdinov, and Joshua Tenenbaum

We are grateful for the www.omniglot.com encyclopedia of writing systems for helping to make this data set possible.
We are grateful for the [Omniglot](http://www.omniglot.com/) encyclopedia of writing systems for helping to make this data set possible.
Binary file added matlab/data_background_small1.mat
Binary file not shown.
Binary file added matlab/data_background_small2.mat
Binary file not shown.
Binary file added python/images_background.zip
Binary file not shown.
Binary file added python/images_background_small1.zip
Binary file not shown.
Binary file added python/images_background_small2.zip
Binary file not shown.
Binary file added python/images_evaluation.zip
Binary file not shown.
Binary file added python/one-shot-classification/all_runs.zip
Binary file not shown.
114 changes: 114 additions & 0 deletions python/one-shot-classification/demo_classification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import numpy as np
import copy
from scipy.ndimage import imread
from scipy.spatial.distance import cdist

# Parameters
nrun = 20 # number of classification runs
fname_label = 'class_labels.txt' # where class labels are stored for each run

def classification_run(folder,f_load,f_cost,ftype='cost'):
# Compute error rate for one run of one-shot classification
#
# Input
# folder : contains images for a run of one-shot classification
# f_load : itemA = f_load('file.png') should read in the image file and process it
# f_cost : f_cost(itemA,itemB) should compute similarity between two images, using output of f_load
# ftype : 'cost' if small values from f_cost mean more similar, or 'score' if large values are more similar
#
# Output
# perror : percent errors (0 to 100% error)
#
assert ((ftype=='cost') | (ftype=='score'))

# get file names
with open(folder+'/'+fname_label) as f:
content = f.read().splitlines()
pairs = [line.split() for line in content]
test_files = [pair[0] for pair in pairs]
train_files = [pair[1] for pair in pairs]
answers_files = copy.copy(train_files)
test_files.sort()
train_files.sort()
ntrain = len(train_files)
ntest = len(test_files)

# load the images (and, if needed, extract features)
train_items = [f_load(f) for f in train_files]
test_items = [f_load(f) for f in test_files ]

# compute cost matrix
costM = np.zeros((ntest,ntrain),float)
for i in range(ntest):
for c in range(ntrain):
costM[i,c] = f_cost(test_items[i],train_items[c])
if ftype == 'cost':
YHAT = np.argmin(costM,axis=1)
elif ftype == 'score':
YHAT = np.argmax(costM,axis=1)
else:
assert False

# compute the error rate
correct = 0.0
for i in range(ntest):
if train_files[YHAT[i]] == answers_files[i]:
correct += 1.0
pcorrect = 100 * correct / ntest
perror = 100 - pcorrect
return perror

def ModHausdorffDistance(itemA,itemB):
# Modified Hausdorff Distance
#
# Input
# itemA : [n x 2] coordinates of "inked" pixels
# itemB : [m x 2] coordinates of "inked" pixels
#
# M.-P. Dubuisson, A. K. Jain (1994). A modified hausdorff distance for object matching.
# International Conference on Pattern Recognition, pp. 566-568.
#
D = cdist(itemA,itemB)
mindist_A = D.min(axis=1)
mindist_B = D.min(axis=0)
mean_A = np.mean(mindist_A)
mean_B = np.mean(mindist_B)
return max(mean_A,mean_B)

def LoadImgAsPoints(fn):
# Load image file and return coordinates of 'inked' pixels in the binary image
#
# Output:
# D : [n x 2] rows are coordinates
I = imread(fn,flatten=True)
I = np.array(I,dtype=bool)
I = np.logical_not(I)
(row,col) = I.nonzero()
D = np.array([row,col])
D = np.transpose(D)
D = D.astype(float)
n = D.shape[0]
mean = np.mean(D,axis=0)
for i in range(n):
D[i,:] = D[i,:] - mean
return D

if __name__ == "__main__":
#
# Running this demo should lead to a result of 38.8 percent errors.
#
# M.-P. Dubuisson, A. K. Jain (1994). A modified hausdorff distance for object matching.
# International Conference on Pattern Recognition, pp. 566-568.
#
# ** Models should be trained on images in 'images_background' directory to avoid
# using images and alphabets used in the one-shot evaluation **
#
perror = np.zeros(nrun)
for r in range(1,nrun+1):
rs = str(r)
if len(rs)==1:
rs = '0' + rs
perror[r-1] = classification_run('run'+rs, LoadImgAsPoints, ModHausdorffDistance, 'cost')
print " run " + str(r) + " (error " + str( perror[r-1] ) + "%)"
total = np.mean(perror)
print " average error " + str(total) + "%"

0 comments on commit 32aee47

Please sign in to comment.