Первые шаги в машинном обучении

МЕНЮ


Искусственный интеллект
Поиск
Регистрация на сайте
Помощь проекту

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


Привет, дорогой друг, ты всегда хотел попробовать машинное обучение, но область выглядела загадочно и сложно? Я хотел бы поделиться с тобой моей историей как я сделал первые шаги в машинном обучении, при нулевом знании Python и высшей математики на небольшом примере.

Преамбула

Я работаю веб разработчиком в консалтинговой компании, и иногда настает момент, когда один проект уже кончился, а на следующий еще не назначили. Каждый оказавшийся на скамейке запасных, чтоб не просто штаны просиживать должен внести вклад в интеллектуальную собственность компании. Как правило это либо создание обучающих материалов по теме, которой владеет автор, либо изучение новой технологии и последующая демонстрация или презентация в конце недели.

Решил, раз есть такая возможность, то попробовать коснуться темы Машинного обучения, поскольку это стильно, модно и молодежно. Из предыдущих познаний в данной теме у меня были только пара презентаций от ведущего разработчика, которые имели скорее популяризаторский нежели информационный оттенок.

Я определил конкретную проблему, чтобы решить ее с помощью машинного обучения и начал копать. Хочу заметить, что имея конечную цель было легче ориентироваться в потоке информации.

Втыкаем лопату

Первым делом я отправился на официальный сайт TensorFlow и прочитал ML for Beginners и TensorFlow for beginners. Материалы на английском.

TensorFlow это поделка команды Google и наиболее популярная библиотека для работы с машинным обучением, которая поддерживает Python, Java, C++, Go, а также возможность использования вычислительных мощностей графической видеокарты для расчетов сложных нейросетей.

В своих поисках я нашел еще одну библиотеку для машинного обучения Scikit-learn ориентированную на Python. Плюс этой библиотеки, в большом количестве алгоритмов для машинного обучения прямо из коробки, что было несомненным плюсом в моем случае, так как презентация в пятницу, и очень хотелось продемонстрировать рабочую модель.

В поисках готовых примеров я наткнулся на туториал по определению языка на котором написан текст с помощью Scikit-learn.

Итак, моей задачей было обучить модель определять наличие SQL инъекции в текстовой строке. (Конечно, можно решить эту задачу с помощью регулярных выражений, но в образовательных целях можно по воробьям стрелять из пушки)

Первым делом, первым делом датасеты...

Тип задачи который я пытаюсь решить это классификация, то есть алгоритм должен в ответ на вскормленные данные выдать мне к какой из категорий эти данные относятся.

Данные в которых алгоритм будет искать закономерности называются features.
Категория, к которой относится та или иная feature, называется label. Важно отметить, что входные данные могут иметь несколько features, но всего один label.

В классическом примере машинного обучения, определения разновидностей цветков ириса по длине пестиков и тычинок, каждый отдельный столбец с информацией о размере это feature, а последний столбец, который означает к какому из подвидов ириса относится цветок с такими значениями это label

Способ, которым я буду решать проблему классификации, называется supervised learning, или обучение под надзором. Это значит, что в процессе обучения алгоритм будет получать и features и labels.

Шаг номер один в решении любой задачи с помощью машинного обучения это сбор данных, на которых эта самая машина и будет учится. В идеальном мире это должны быть реальные данные, но, к сожалению, в интернете я не смог найти ничего что бы меня удовлетворило. Решено было сгенерировать данные самостоятельно.

Я написал скрипт, который генерировал случайные адреса электронной почты и SQL инъекции. В итоге в моем csv файле получалось три типа данных: случайные имейлы (20 тыс.), случайные имейлы с SQL инъекцией (20 тыс.) и чистые SQL инъекции (10 тыс.). Выглядело это примерно вот так:

Теперь исходные данные нужно считать. Функция возвращает лист X, в котором содержатся features, лист Y, в котором содержатся labels для каждой feature и лист label_names, который просто содержит текстовое определения для labels, нужен для удобства при выводе результатов.

import csv  def get_dataset():    X = []    y = []    label_names = ["safe data","Injected email"]    with open('trainingSet.csv') as csvfile:        readCSV = csv.reader(csvfile, delimiter=' ')        for row in readCSV:            splitted = row[0].split(',')            X.append(splitted[0])            y.append(splitted[1])                         print("  Data set features {0}". format(len(X)))    print("Data set labels   {0} ". format(len(y)))     print(X)     return X, y, label_names 

Далее эти данные нужно разбить на тренировочный сет и на тестовый. В этом нам поможет заботливо написанная для нас функция cross_validation.train_test_split(), которая перетасует записи и вернет нам четыре сета данных — два тренировочных и два тестовых для features и labels.

# Split the dataset on training and testing sets X_train, X_test, y_train, y_test = cross_validation.train_test_split(X,y,test_size=0.2,random_state=0)

Затем мы инициализируем объект vectorizer, который будет считывать переданные в него данные по одному символу, комбинировать их в N-граммы и переводить в числовые векторы, который способен воспринимать алгоритм машинного обучения.

#Setting up vectorizer that will convert dataset into vectors using n-gram vectorizer = feature_extraction.text.TfidfVectorizer(ngram_range=(1, 4), analyzer='char') 

Скармливаем данные

Следующий шаг мы инициализируем pipeline и передадим в него ранее созданный vectorizer и алгоритм, которым мы хотим анализировать наш дата сет. В данном мы будем использовать алгоритм логистической регрессии.

#Setting up pipeline to flow data though vectorizer to the liner model implementation pipe = pipeline.Pipeline([('vectorizer', vectorizer), ('clf', linear_model.LogisticRegression())]) 

Модель готова к перевариванию данных. Теперь просто передаем тренировочные сеты features и labels в наш pipeline и модель начинает обучение. Следующей строкой мы пропускаем тестовый сет features через pipeline, но теперь мы используем predict, чтобы получить число правильно угаданных данных.

#Pass training set of features and labels though pipe. pipe.fit(X_train, y_train)  #Test model accuracy by running feature test set y_predicted = pipe.predict(X_test) 

Если хочется узнать насколько модель точна в предсказаниях, можно сравнить угаданные данные и тестовый лист labels.

print(metrics.classification_report(y_test, y_predicted,target_names=label_names))

Точность модели определяется величиной от 0 до 1, и можно перевести в проценты. Эта модель дает правильный ответ в 100% случаев. Конечно, используя реальные данные, подобного результата будет добиться не так просто, да и задача достаточно простая.

Последний финальный штрих это сохранить модель в обученном виде, чтоб ее можно было без повторного обучения использовать в любой другой python программе. Мы сериализуем модель в pickle файл с помощью встроенной в Scikit-learn функции:

#Save model into pickle. Built in serializing tool joblib.dump(pipe, 'injection_model.pkl') 

Небольшая демонстрация того, как использовать сериализованную модель в другой программе.

import numpy as np from sklearn.externals import joblib  #Load classifier from the pickle file clf = joblib.load('injection_model.pkl')  #Set of test data input_data = ["aselectndwdpyrey@gmail.com",            "andrew@microsoft.com'",            "a.johns@deloite.com",            "'",            "select@mail.jp",            "update11@nebuzar.com",            "' OR 1=1",            "asdasd@sick.com'",            "andrew@mail' OR 1=1",            "an'drew@bark.1ov111.com",            "andrew@gmail.com'"]  predicted_attacks = clf.predict(input_data).astype(np.int) label_names = ["Safe Data", "SQL Injection"]  for email, item in zip(input_data, predicted_attacks):  print(u' {} ----> {}'.format(label_names[item], email)) 

На выходе мы получим вот такой результат:

Как видите, модель достаточно уверенно определяет SQL инъекции.

Заключение

В итоге мы имеем тренированную модель для определения SQL инъекций, в теории, мы можем воткнуть ее в серверную часть, и в случае определения инъекции перенаправлять все запросы за фальшивую базу данных, чтоб отвадить взгляд от других возможных уязвимостей. Для демонстрации в конце недели я написал небольшой REST API на Flask.

Это были мои первые шаги в области машинного обучения. Надеюсь, что я смогу вдохновить тех, кто так же как и я долгое время с интересом смотрел на машинное обучение, но боялся прикоснутся к нему.

Полный код

 from sklearn import ensemble from sklearn import feature_extraction from sklearn import linear_model from sklearn import pipeline from sklearn import cross_validation from sklearn import metrics from sklearn.externals import joblib  import load_data import pickle  # Load the dataset from the csv file. Handled by load_data.py. Each email is split in characters and each one has label assigned X, y, label_names = load_data.get_dataset()  # Split the dataset on training and testing sets X_train, X_test, y_train, y_test = cross_validation.train_test_split(X,y,test_size=0.2,random_state=0)  #Setting up vectorizer that will convert dataset into vectors using n-gram vectorizer = feature_extraction.text.TfidfVectorizer(ngram_range=(1, 4), analyzer='char')  #Setting up pipeline to flow data though vectorizer to the liner model implementation pipe = pipeline.Pipeline([('vectorizer', vectorizer), ('clf', linear_model.LogisticRegression())])  #Pass training set of features and labels though pipe. pipe.fit(X_train, y_train)  #Test model accuracy by running feature test set y_predicted = pipe.predict(X_test)  print(metrics.classification_report(y_test, y_predicted,target_names=label_names))  #Save model into pickle. Built in serializing tool joblib.dump(pipe, 'injection_model.pkl') 

Справочные Материалы

Оставляю список полезных ресурсов, которые помогли мне с данным проектом (почти все они на английском)

Tensorflow for begginers
Scikit-Learn Tutorials
Building Language Detector via Scikit-Learn

Нашел несколько отличных статей на Medium включая серию из восьми статей, которые дают хорошее представление, о машинном обучении на простых примерах. (UPD: русский перевод этих же статей)


Источник: habrahabr.ru

Комментарии: