Обзор библиотек для машинного обучения на Python

Материал из Викиконспекты
Версия от 20:29, 22 января 2019; Alexey Katsman (обсуждение | вклад) (Сверточная нейронная сеть)
Перейти к: навигация, поиск

Scikit-learn

Описание

Scikit-learn[1] — библиотека машинного обучения на языке программирования Python с открытым исходным кодом. Содержит реализации практически всех возможных преобразований, и нередко ее одной хватает для полной реализации модели. В данной библиотеки реализованы методы разбиения датасета на тестовый и обучающий, вычисление основных метрик над наборами данных, проведение кросс-валидации. В библиотеке также есть основные алгоритмы машинного обучения: линейной регрессии, (и ее модификаций Лассо, гребневой регрессии), опорных векторов, решающих деревьев и лесов и др. Есть и реализации основных методов кластеризации. Кроме того, библиотека содержит постоянно используемые исследователями методы работы с параметрами (фичами): например, понижение размерности методом главных компонент. Частью пакета является библиотека imblearn[2], позволяющая работать с разбалансированными выборками и генерировать новые значения.

Примеры кода

Логистическая регрессия

Основная статья: Логистическая регрессия

Загрузка датасета:

 from sklearn.datasets import load_digits
 digits = load_digits()

Вывод первых трех тренировочных данных для визуализации:

 import numpy as np
 import matplotlib.pyplot as plt
 
 plt.figure(figsize=(20,4))
 for index, (image, label) in enumerate(zip(digits.data[0:3], digits.target[0:3])):
   plt.subplot(1, 3, index + 1)
   plt.imshow(np.reshape(image, (8,8)), cmap=plt.cm.gray)
   plt.title('Training: %i\n' % label, fontsize = 20)

Разбиение датасета на тренировочный и тестовый:

 from sklearn.model_selection import train_test_split
 x_train, x_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.25, random_state=0)

Построение и обучение модели:

 from sklearn.linear_model import LogisticRegression
 lr = LogisticRegression()
 lr.fit(x_train, y_train)
 predictions = lr.predict(x_test)

Перцептрон

Основная статья: Нейронные сети, перцептрон

Загрузка датасета:

 from sklearn import datasets
 iris = datasets.load_iris()
 X = iris.data
 y = iris.target

Разбиение датасета на тренировочный и тестовый:

 from sklearn.model_selection import train_test_split
 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)

Трансформация признаков:

 from sklearn.preprocessing import StandardScaler
 scaler = StandardScaler()
 scaler.fit(X_train)
 X_train = scaler.transform(X_train)
 X_test = scaler.transform(X_test)

Построение и обучение модели:

 from sklearn.neural_network import MLPClassifier
 mlp = MLPClassifier(hidden_layer_sizes=(10, 10, 10), max_iter=1000)
 mlp.fit(X_train, y_train.values.ravel())
 predictions = mlp.predict(X_test)

Оценка алгоритма:

 from sklearn.metrics import classification_report, confusion_matrix
 print(confusion_matrix(y_test,predictions))
 print(classification_report(y_test,predictions))

Theano

Описание

Theano[3] — расширение языка программирования Python, позволяющее эффективно вычислять математические выражения, содержащие многомерные массивы. Библиотека предоставляет базовый набор инструментов для конфигурации нейронных сетей и их обучения. Наибольшее признание данная библиотека получила в задачах машинного обучения при решении задач оптимизации. Она позволяет использовать возможности GPU без изменения кода программы, что делает ее незаменимой при выполнении ресурсоемких задач.

Примеры кода

Логистическая регрессия

Основная статья: Логистическая регрессия.

Реализация логистической регрессии для классификации цифр из датасета MNIST[4]:

 from __future__ import print_function
 __docformat__ = 'restructedtext en'
 import six.moves.cPickle as pickle
 import gzip
 import os
 import sys
 import timeit
 import numpy
 import theano
 import theano.tensor as T
 
 class LogisticRegression(object):
   def __init__(self, input, n_in, n_out):
     self.W = theano.shared(
       value=numpy.zeros(
         (n_in, n_out),
         dtype=theano.config.floatX
       ),
       name='W',
       borrow=True
     )
     self.b = theano.shared(
       value=numpy.zeros(
         (n_out,),
         dtype=theano.config.floatX
       ),
       name='b',
       borrow=True
     )
     self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
     self.y_pred = T.argmax(self.p_y_given_x, axis=1)
     self.params = [self.W, self.b]
     self.input = input
   def negative_log_likelihood(self, y):
     return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])
 
 def load_data(dataset):
   data_dir, data_file = os.path.split(dataset)
   if data_dir == "" and not os.path.isfile(dataset):
     new_path = os.path.join(
       os.path.split(__file__)[0],
       "..",
       "data",
       dataset
     )
     if os.path.isfile(new_path) or data_file == 'mnist.pkl.gz':
       dataset = new_path
   if (not os.path.isfile(dataset)) and data_file == 'mnist.pkl.gz':
     from six.moves import urllib
     origin = (
       'http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz'
     )
     print('Downloading data from %s' % origin)
     urllib.request.urlretrieve(origin, dataset)
   with gzip.open(dataset, 'rb') as f:
     try:
       train_set, valid_set, test_set = pickle.load(f, encoding='latin1')
     except:
       train_set, valid_set, test_set = pickle.load(f)
   def shared_dataset(data_xy, borrow=True):
     data_x, data_y = data_xy
     shared_x = theano.shared(numpy.asarray(data_x,
                                            dtype=theano.config.floatX),
                              borrow=borrow)
     shared_y = theano.shared(numpy.asarray(data_y,
                                            dtype=theano.config.floatX),
                              borrow=borrow)
     return shared_x, T.cast(shared_y, 'int32')
   test_set_x, test_set_y = shared_dataset(test_set)
   valid_set_x, valid_set_y = shared_dataset(valid_set)
   train_set_x, train_set_y = shared_dataset(train_set)
   rval = [(train_set_x, train_set_y), (valid_set_x, valid_set_y),
           (test_set_x, test_set_y)]
   return rval
 
 def sgd_optimization_mnist(learning_rate=0.13, n_epochs=1000,
                            dataset='mnist.pkl.gz',
                            batch_size=600):
   datasets = load_data(dataset)
   train_set_x, train_set_y = datasets[0]
   valid_set_x, valid_set_y = datasets[1]
   test_set_x, test_set_y = datasets[2]
   n_train_batches = train_set_x.get_value(borrow=True).shape[0]
   n_valid_batches = valid_set_x.get_value(borrow=True).shape[0]
   n_test_batches = test_set_x.get_value(borrow=True).shape[0]
   index = T.lscalar()
   x = T.matrix('x')
   y = T.ivector('y')
   classifier = LogisticRegression(input=x, n_in=28 * 28, n_out=10)
   cost = classifier.negative_log_likelihood(y)
   test_model = theano.function(
       inputs=[index],
       outputs=classifier.errors(y),
       givens={
           x: test_set_x[index * batch_size: (index + 1) * batch_size],
           y: test_set_y[index * batch_size: (index + 1) * batch_size]
       }
   )
   validate_model = theano.function(
       inputs=[index],
       outputs=classifier.errors(y),
       givens={
           x: valid_set_x[index * batch_size: (index + 1) * batch_size],
           y: valid_set_y[index * batch_size: (index + 1) * batch_size]
       }
   )
   g_W = T.grad(cost=cost, wrt=classifier.W)
   g_b = T.grad(cost=cost, wrt=classifier.b)
   updates = [(classifier.W, classifier.W - learning_rate * g_W),
              (classifier.b, classifier.b - learning_rate * g_b)]
   train_model = theano.function(
       inputs=[index],
       outputs=cost,
       updates=updates,
       givens={
           x: train_set_x[index * batch_size: (index + 1) * batch_size],
           y: train_set_y[index * batch_size: (index + 1) * batch_size]
       }
   )
   patience = 5000
   patience_increase = 2
   improvement_threshold = 0.995
   validation_frequency = min(n_train_batches, patience // 2)
   best_validation_loss = numpy.inf
   test_score = 0.
   start_time = timeit.default_timer()
   done_looping = False
   epoch = 0
   while (epoch < n_epochs) and (not done_looping):
       epoch = epoch + 1
       for minibatch_index in range(n_train_batches):
           minibatch_avg_cost = train_model(minibatch_index)
           iter = (epoch - 1) * n_train_batches + minibatch_index
           if (iter + 1) % validation_frequency == 0:
               validation_losses = [validate_model(i)
                                    for i in range(n_valid_batches)]
               this_validation_loss = numpy.mean(validation_losses)
               print(
                   'epoch %i, minibatch %i/%i, validation error %f %%' %
                   (
                       epoch,
                       minibatch_index + 1,
                       n_train_batches,
                       this_validation_loss * 100.
                   )
               )
               if this_validation_loss < best_validation_loss:
                   if this_validation_loss < best_validation_loss *  \
                      improvement_threshold:
                       patience = max(patience, iter * patience_increase)
                   best_validation_loss = this_validation_loss
                   test_losses = [test_model(i)
                                  for i in range(n_test_batches)]
                   test_score = numpy.mean(test_losses)
                   print(
                       (
                           '     epoch %i, minibatch %i/%i, test error of'
                           ' best model %f %%'
                       ) %
                       (
                           epoch,
                           minibatch_index + 1,
                           n_train_batches,
                           test_score * 100.
                       )
                   )
                   with open('best_model.pkl', 'wb') as f:
                       pickle.dump(classifier, f)
           if patience <= iter:
               done_looping = True
               break
   end_time = timeit.default_timer()
   print(
       (
           'Optimization complete with best validation score of %f %%,'
           'with test performance %f %%'
       )
       % (best_validation_loss * 100., test_score * 100.)
   )
   print('The code run for %d epochs, with %f epochs/sec' % (
       epoch, 1. * epoch / (end_time - start_time)))
   print(('The code for file ' +
          os.path.split(__file__)[1] +
          ' ran for %.1fs' % ((end_time - start_time))), file=sys.stderr)
 
 def predict():
   classifier = pickle.load(open('best_model.pkl'))
   predict_model = theano.function(
       inputs=[classifier.input],
       outputs=classifier.y_pred)
   dataset='mnist.pkl.gz'
   datasets = load_data(dataset)
   test_set_x, test_set_y = datasets[2]
   test_set_x = test_set_x.get_value()
   predicted_values = predict_model(test_set_x[:10])
   print("Predicted values for the first 10 examples in test set:")
   print(predicted_values)
 
 if __name__ == '__main__':
   sgd_optimization_mnist()

Tensorflow

Описание

Tensorflow[5] — библиотека, разработанная корпорацией Google для работы с тензорами, используется для построения нейронных сетей. Поддержка вычислений на видеокартах имеет поддержку языка программирования C++. На основе данной библиотеки строятся более высокоуровневые библиотеки для работы с нейронными сетями на уровне целых слоев. Так, некоторое время назад популярная библиотека Keras стала использовать Tensorflow как основной бэкенд для вычислений вместо аналогичной библиотеки Theano. Для работы на видеокартах NVIDIA используется библиотека cuDNN. Если вы работаете с картинками (со сверточными нейросетями), скорее всего, придется использовать данную библиотеку.

Примеры кода

Сверточная нейронная сеть

Основная статья: Сверточные нейронные сети.

Реализация сверточной нейронной сети для классификации цифр из датасета MNIST[6]:

 from __future__ import division, print_function, absolute_import
 import tensorflow as tf
 
 # Import MNIST data
 from tensorflow.examples.tutorials.mnist import input_data
 mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)
 
 # Training Parameters
 learning_rate = 0.001
 num_steps = 200
 batch_size = 128
 display_step = 10
 
 # Network Parameters
 num_input = 784 # MNIST data input (img shape: 28*28)
 num_classes = 10 # MNIST total classes (0-9 digits)
 dropout = 0.75 # Dropout, probability to keep units
 
 # tf Graph input
 X = tf.placeholder(tf.float32, [None, num_input])
 Y = tf.placeholder(tf.float32, [None, num_classes])
 keep_prob = tf.placeholder(tf.float32) # dropout (keep probability)
 
 # Create some wrappers for simplicity
 def conv2d(x, W, b, strides=1):
   # Conv2D wrapper, with bias and relu activation
   x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')
   x = tf.nn.bias_add(x, b)
   return tf.nn.relu(x)
 
 def maxpool2d(x, k=2):
   # MaxPool2D wrapper
   return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, k, k, 1],
                         padding='SAME')
 
 # Create model
 def conv_net(x, weights, biases, dropout):
   # MNIST data input is a 1-D vector of 784 features (28*28 pixels)
   # Reshape to match picture format [Height x Width x Channel]
   # Tensor input become 4-D: [Batch Size, Height, Width, Channel]
   x = tf.reshape(x, shape=[-1, 28, 28, 1])
   # Convolution Layer
   conv1 = conv2d(x, weights['wc1'], biases['bc1'])
   # Max Pooling (down-sampling)
   conv1 = maxpool2d(conv1, k=2)
   # Convolution Layer
   conv2 = conv2d(conv1, weights['wc2'], biases['bc2'])
   # Max Pooling (down-sampling)
   conv2 = maxpool2d(conv2, k=2)
   # Fully connected layer
   # Reshape conv2 output to fit fully connected layer input
   fc1 = tf.reshape(conv2, [-1, weights['wd1'].get_shape().as_list()[0]])
   fc1 = tf.add(tf.matmul(fc1, weights['wd1']), biases['bd1'])
   fc1 = tf.nn.relu(fc1)
   # Apply Dropout
   fc1 = tf.nn.dropout(fc1, dropout)
   # Output, class prediction
   out = tf.add(tf.matmul(fc1, weights['out']), biases['out'])
   return out
 
 # Store layers weight & bias
 weights = {
   # 5x5 conv, 1 input, 32 outputs
   'wc1': tf.Variable(tf.random_normal([5, 5, 1, 32])),
   # 5x5 conv, 32 inputs, 64 outputs
   'wc2': tf.Variable(tf.random_normal([5, 5, 32, 64])),
   # fully connected, 7*7*64 inputs, 1024 outputs
   'wd1': tf.Variable(tf.random_normal([7*7*64, 1024])),
   # 1024 inputs, 10 outputs (class prediction)
   'out': tf.Variable(tf.random_normal([1024, num_classes]))
 }
 
 biases = {
   'bc1': tf.Variable(tf.random_normal([32])),
   'bc2': tf.Variable(tf.random_normal([64])),
   'bd1': tf.Variable(tf.random_normal([1024])),
   'out': tf.Variable(tf.random_normal([num_classes]))
 }
 
 # Construct model
 logits = conv_net(X, weights, biases, keep_prob)
 prediction = tf.nn.softmax(logits)
 
 # Define loss and optimizer
 loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
   logits=logits, labels=Y))
 optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
 train_op = optimizer.minimize(loss_op)
 
 # Evaluate model
 correct_pred = tf.equal(tf.argmax(prediction, 1), tf.argmax(Y, 1))
 accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
 
 # Initialize the variables (i.e. assign their default value)
 init = tf.global_variables_initializer()
 
 # Start training
 with tf.Session() as sess:
   # Run the initializer
   sess.run(init)
   for step in range(1, num_steps+1):
     batch_x, batch_y = mnist.train.next_batch(batch_size)
     # Run optimization op (backprop)
     sess.run(train_op, feed_dict={X: batch_x, Y: batch_y, keep_prob: 0.8})
     if step % display_step == 0 or step == 1:
       # Calculate batch loss and accuracy
       loss, acc = sess.run([loss_op, accuracy], feed_dict={X: batch_x,
                                                            Y: batch_y,
                                                            keep_prob: 1.0})
       print("Step " + str(step) + ", Minibatch Loss= " + \
             "{:.4f}".format(loss) + ", Training Accuracy= " + \
             "{:.3f}".format(acc))
   print("Optimization Finished!")
   # Calculate accuracy for 256 MNIST test images
   print("Testing Accuracy:", \
     sess.run(accuracy, feed_dict={X: mnist.test.images[:256],
                                   Y: mnist.test.labels[:256],
                                   keep_prob: 1.0}))

Keras

Описание

Keras[7] — библиотека для построения нейронных сетей, поддерживающая основные виды слоев и структурные элементы. Поддерживает как рекуррентные, так и сверточные нейросети, имеет в своем составе реализацию известных архитектур нейросетей (например, VGG16). Некоторое время назад слои из данной библиотеки стали доступны внутри библиотеки Tensorflow. Существуют готовые функции для работы с изображениями и текстом. Интегрирована в Apache Spark с помощью дистрибутива dist-keras. Данная библиотека позволяет на более высоком уровне работать с нейронными сетями. В качестве библиотеки для бэкенда может использоваться как Tensorflow, так и Theano.

Примеры кода

Сверточная нейронная сеть

Основная статья: Сверточные нейронные сети.

Реализация сверточной нейронной сети для классификации текста:

 from __future__ import print_function
 from keras.preprocessing import sequence
 from keras.models import Sequential
 from keras.layers import Dense, Dropout, Activation
 from keras.layers import Embedding
 from keras.layers import Conv1D, GlobalMaxPooling1D
 from keras.datasets import imdb
 
 # set parameters:
 max_features = 5000
 maxlen = 400
 batch_size = 32
 embedding_dims = 50
 filters = 250
 kernel_size = 3
 hidden_dims = 250
 epochs = 2
 
 (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
 print(len(x_train), 'train sequences')
 print(len(x_test), 'test sequences')
 
 print('Pad sequences (samples x time)')
 x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
 x_test = sequence.pad_sequences(x_test, maxlen=maxlen)
 print('x_train shape:', x_train.shape)
 print('x_test shape:', x_test.shape)
 
 model = Sequential()
 
 model.add(Embedding(max_features,
                     embedding_dims,
                     input_length=maxlen))
 model.add(Dropout(0.2))  
 model.add(Conv1D(filters,
                  kernel_size,
                  padding='valid',
                  activation='relu',
                  strides=1))
 model.add(GlobalMaxPooling1D())
 model.add(Dense(hidden_dims))
 model.add(Dropout(0.2))
 model.add(Activation('relu'))
 model.add(Dense(1))
 model.add(Activation('sigmoid'))
 
 model.compile(loss='binary_crossentropy',
               optimizer='adam',
               metrics=['accuracy'])
 model.fit(x_train, y_train,
           batch_size=batch_size,
           epochs=epochs,
validation_data=(x_test, y_test))