J'ai récemment entendu une rumeur notMNIST J'ai écrit un processus pour gérer un ensemble de données en Python, donc je vais le publier: blush:
MNIST est un ensemble de données de test de nombres manuscrits que de nombreuses personnes qui apprennent l'apprentissage automatique connaissent, mais ce notMNIST est manuscrit. Il s'agit d'un ensemble de données d'images d'alphabets exprimés dans diverses polices au lieu de nombres.
Si vous essayez de visualiser le contenu, vous verrez l'ensemble de données suivant. Les lettres au début de l'image sont l'alphabet que l'image représente et l'image correspondante est affichée. Regardez le deuxième en partant de la droite sur la première ligne. Ça ne ressemble pas du tout à "je", c'est une maison, non? Ceci: sweat_smile: Avec ce genre de sentiment, même si une personne voit une ligne, elle contient des données suspectes, mais je pense que c'est un sujet très intéressant.
La page officielle de notMNIST est http://yaroslavvb.blogspot.jp/2011/09/notmnist-dataset.html Ainsi, une personne nommée Yaroslav Bulatov est créée.
Tout d'abord http://yaroslavvb.com/upload/notMNIST/ Aller et là notMNIST_large.tar.gz Veuillez télécharger les données depuis.
Puisqu'il est compressé avec tar.gz, si vous le décompressez avec un outil de décompression, etc., le cas échéant notMNIST_large Des dossiers sont créés et des dossiers pour chaque alphabet de A, B, C ... sont créés dans les sous-dossiers. J'écrirai le processus pour lire ceci en Python. J'utilise un Jupyter Notebook, auquel cas je veux que le fichier .ipynb se trouve dans le même répertoire que ce dossier notMNIST_large. Pour .py, assurez-vous que le fichier .py est également créé dans le même répertoire.
L'ensemble de code est également téléchargé sur Github, mais je l'écrirai également ici.
Installer diverses bibliothèques,
from __future__ import division
import sys, os, pickle
import numpy as np
import numpy.random as rd
from scipy.misc import imread
import matplotlib.pyplot as plt
%matplotlib inline
Définissez une fonction pour pickle, une fonction pour afficher une image, etc.
image_size = 28
depth = 255
def unpickle(filename):
with open(filename, 'rb') as fo:
_dict = pickle.load(fo)
return _dict
def to_pickle(filename, obj):
with open(filename, 'wb') as f:
#pickle.dump(obj, f, -1)
pickle.Pickler(f, protocol=2).dump(obj)
def count_empty_file(folder):
cnt = 0
for file in os.listdir(folder):
if os.stat(os.path.join(folder, file)).st_size == 0:
cnt += 1
return cnt
Je veux enregistrer l'étiquette en tant que type int, alors préparez un dictionnaire pour la conversion.
label_conv = {a: i for a, i in zip('ABCDEFGHIJ', range(10))}
num2alpha = {i: a for i,a in zip(range(10), 'ABCDEFGHIJ')}
Lisez chaque fichier image dans le dossier et enregistrez-le dans un ndarray numpy. En même temps, préparez les données d'étiquette avec le nom du dossier comme étiquette. Après lecture, stockez les données d'image dans «données» et les données d'étiquette dans «cible» au format dictionnaire, et enregistrez l'objet sous forme de fichier avec pickle. Parfois, il y a un fichier corrompu et la taille est 0 et il ne peut pas être lu, donc le traitement de saut est inclus comme contre-mesure pour de telles choses et des choses qui provoquent des erreurs de lecture.
#Vérifier l'existence du dossier à lire
assert os.path.exists('notMNIST_large')
# assert os.path.exists('notMNIST_small') #Lorsque vous lisez petit, veuillez le restaurer pour vérification.
for root_dir in ['notMNIST_large']: # ['notMNIST_small', 'notMNIST_large']: #Si vous utilisez également petit, sélectionnez les deux
folders = [os.path.join(root_dir, d) for d in sorted(os.listdir(root_dir))
if os.path.isdir(os.path.join(root_dir, d))]
#Faire un cadre
file_cnt = 0
for folder in folders:
label_name = os.path.basename(folder)
file_list = os.listdir(folder)
file_cnt += len(file_list)-count_empty_file(folder)
dataset = np.ndarray(shape=(file_cnt, image_size*image_size), dtype=np.float32)
labels = np.ndarray(shape=(file_cnt), dtype=np.int)
last_num = 0 #Dernier index du caractère précédent
for folder in folders:
file_list = os.listdir(folder)
file_cnt = len(file_list)-count_empty_file(folder)
label_name = os.path.basename(folder)
labels[last_num:(last_num+file_cnt)] = label_conv[label_name]
#label = np.array([label_name] * file_cnt)
skip = 0
for i, file in enumerate(file_list):
#Ignorer la taille du fichier 0
if os.stat(os.path.join(folder, file)).st_size == 0:
skip += 1
continue
try:
data = imread(os.path.join(folder, file))
data = data.astype(np.float32)
data /= depth # 0-Convertir en 1 données
dataset[last_num+i-skip, :] = data.flatten()
except:
skip += 1
print 'error {}'.format(file)
continue
last_num += i-skip
notmnist = {}
notmnist['data'] = dataset
notmnist['target'] = labels
to_pickle('{}.pkl'.format(root_dir), notmnist)
Lorsque vous l'utilisez, décochez-le, lisez le fichier et extrayez-le en tant qu'objet. Si nécessaire, modifiez la plage de valeurs sur 0-1 ou divisez-la en données d'apprentissage et données de validation.
from sklearn.cross_validation import train_test_split
notmnist = unpickle('notMNIST_large.pkl') #NotMNIST dans le même dossier_large.Supposons qu'il contienne pkl.
notmnist_data = notmnist['data']
notmnist_target = notmnist['target']
notmnist_data = notmnist_data.astype(np.float32)
notmnist_target = notmnist_target.astype(np.int32)
notmnist_data /= 255 # 0-Convertir en 1 données
#75 données d'entraînement%, Définissez les données de vérification avec le nombre restant
x_train, x_test, y_train, y_test = train_test_split(notmnist_data, notmnist_target)
Si vous souhaitez visualiser à quoi ressemble l'image chargée, essayez le processus d'affichage avec la fonction suivante.
def draw_digit(digits):
size = 28
plt.figure(figsize=(len(digits)*1.5, 2))
for i, data in enumerate(digits):
plt.subplot(1, len(digits), i+1)
X, Y = np.meshgrid(range(size),range(size))
Z = data[0].reshape(size,size) # convert from vector to 28x28 matrix
Z = Z[::-1,:] # flip vertical
plt.xlim(0,27)
plt.ylim(0,27)
plt.pcolor(X, Y, Z)
plt.gray()
plt.title(num2alpha[data[1]])
plt.tick_params(labelbottom="off")
plt.tick_params(labelleft="off")
plt.show()
Il est affiché sur 10 lignes et 10 colonnes.
[draw_digit2([[notmnist_data[idx], notmnist_target[idx]] for idx in rd.randint(len(dataset), size=10)]) for i in range(10)]
Puisque je l'ai lu avec beaucoup d'efforts, je vais essayer la classification avec Random Forest. (Étant donné que le nombre de machines d'apprentissage faibles est défini sur 100, il faudra un certain temps pour apprendre.)
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(n_estimators=100)
clf = clf.fit(x_train, y_train)
Pour l'instant, regardons le taux d'erreur de réaffectation.
#Taux d'erreur de réaffectation
pred = clf.predict(x_train)
result = [y==p for y, p in zip(y_train,pred)]
np.sum(result)/len(pred)
out
0.99722555413319358
#Vérification des performances de généralisation
pred = clf.predict(x_test)
result = [y==p for y, p in zip(y_test,pred)]
np.sum(result)/len(pred)
Les performances de généralisation sont également bonnes à 91%.
out
0.91262407487205077
Visualisons le résultat de la prédiction.
#Visualisez les résultats
rd.seed(123)
[draw_digit([[x_test[idx], y_test[idx], pred[idx]] for idx in rd.randint(len(x_test), size=10)]) for i in range(10)]
La plupart des gens peuvent répondre à de mauvaises choses qui sont probablement fausses et des réponses presque correctes qui peuvent être reconnues comme des alphabets: sourire:
Recommended Posts