Разрабатываем и развёртываем собственную платформу ИИ с Python и Django

МЕНЮ


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

ТЕМЫ


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

Авторизация



RSS


RSS новости


Взлёт искусственного интеллекта привёл к популярности платформ машинного обучения MLaaS. Если ваша компания не собирается строить фреймворк и развёртывать свои собственные модели, есть шанс, что она использует некоторые платформы MLaaS, например H2O или KNIME. Многие исследователи данных, которые хотят сэкономить время, пользуются этими инструментами, чтобы быстро прототипировать и тестировать модели, а позже решают, будут ли их модели работать дальше. 

Но не бойтесь всей этой инфраструктуры; чтобы понять эту статью, достаточно минимума знаний языка Python и фреймворка Django.  Специально к старту нового потока курса по машинному обучению в этом посте покажем, как быстро создать собственную платформу ML, способную запускать самые популярные алгоритмы на лету.
Портрет Орнеллы Мути Джозефа Айерле (фрагмент), рассчитанный с помощью технологии искусственного интеллекта.


Прежде всего взгляните, пожалуйста, на сайт, который я разработал для этого проекта, и позвольте мне показать вам краткое введение в то, что можно сделать с этой платформой, в этом видео.

Как видите, вы выбираете самые популярные модели с контролируемым и неконтролируемым обучением и запускаете их всего одним щелчком мыши. Если хочется попробовать те же наборы данных, что и в видео, вы можете скачать их здесь.  Круто, давайте посмотрим, как это сделать! Возможно, вы работаете на ноутбуке или на облачном сервере, я использовал сервер Digital Ocean, приложение работает на Nginx и Gunicorn, и я подробно расскажу о том, как развёртывать его: это может быть полезно, когда нужно развёртывать приложения на Linux-сервере каждый день. Давайте начнём настраивать наше окружение с некоторых установок:

sudo apt-get update sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx # install python postgresql and nginx # now install a postgresql database sudo -u postgres psql  #log in to psql CREATE DATABASE myproject;   #give a name to your database project  CREATE USER myprojectuser WITH PASSWORD 'password';   # create user and password ALTER ROLE myprojectuser SET client_encoding TO 'utf8'; ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed'; ALTER ROLE myprojectuser SET timezone TO 'UTC'; q # log out  # cd to the folder where you want to keep your environment sudo -H pip3 install env virtualenv env # create a virtual environment for this project source myprojectenv/bin/activate pip install django gunicorn psycopg2 #install django and gunicorn  # now cd to the directory where you want to create your project, in my case cd /www/var django-admin.py startproject trainyourmodel #cd trainyourmodel django-admin startapp portal # create an app for the views of this app #cd trainyourmodel again and nano settings.py 

# now we configure our settings.py file  DATABASES = {     'default': {         'ENGINE': 'django.db.backends.postgresql_psycopg2',         'NAME': 'myproject',         'USER': 'myprojectuser',         'PASSWORD': 'password',         'HOST': 'localhost',         'PORT': '',     } }   STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static/') 

После этого всё, что Вам нужно сделать, — это настроить Вашу конфигурацию для сервиса Gunicorn: 

sudo nano /etc/systemd/system/gunicorn.service

[Unit] Description=gunicorn daemon After=network.target  [Service] User=root Group=www-data WorkingDirectory=/var/www/trainyourmodel ExecStart=/opt/env/bin/gunicorn --access-logfile - --workers 3 --bind unix:/var/www/trainyourmodel/trainyourmodel.sock trainyourmodel.wsgi:application

sudo systemctl start gunicorn sudo systemctl enable gunicorn sudo systemctl status gunicorn  gunicorn --bind 0.0.0.0:8000 trainyourmodel.wsgi 

И для Nginx: 

sudo nano /etc/nginx/sites-available/trainyourmodel

server {     listen 80;     server_name server_domain_or_IP;      location = /favicon.ico { access_log off; log_not_found off; }     location /static/ {         root /var/www/trainyourmodel;     }      location / {         include proxy_params;         proxy_pass http://unix:/var/www/trainyourmodel/trainyourmodel.sock;     } } #copy the same file also in sudo nano /etc/nginx/sites-enabled/trainyourmodel 

sudo systemctl restart nginx sudo systemctl status nginx

Теперь всё готово, и вы можете просто клонировать код из моего GitHub-репозитория (текущая ветка — releasee-1.2) и установить все нужные пакеты, просто выполнив команду: 
pip -install -r requirements.txt

Проверьте технические характеристики вашей системы, чтобы убедиться, что она соответствует требованиям (стоят нужные версии Python, Django и т. д.). После этого вы увидите типичные папки структуры проекта Django, а именно:

  • Папка проекта trainyourmodel с файлом settings.py.
  • Папка приложения под названием Portral c файлом views.py.
  • Папка шаблонов для кода .html.

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

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

Прежде всего мы импортируем все библиотеки, которые нам понадобятся для наших моделей машинного обучения и построения красивых графиков онлайн (Pandas, NumPy, sci-kit-learn, TensorFlow, Keras, Seaborn, Plotly и т. д.). 

# This Python file uses the following encoding in format utf-8 import plotly import plotly.express as px import plotly.graph_objects as go from django.core.mail import send_mail, BadHeaderError, EmailMessage  import io import csv from io import BytesIO import base64 import functools import operator import random import unicodedata import datetime import pandas as pd import seaborn as sns import numpy as np from efficient_apriori import apriori  from sklearn import metrics from sklearn.cross_validation import train_test_split from sklearn.metrics import classification_report, confusion_matrix  from sklearn.ensemble import RandomForestClassifier from sklearn.cluster import KMeans from sklearn.svm import SVC from sklearn.grid_search import GridSearchCV from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.linear_model import LinearRegression from sklearn.naive_bayes import GaussianNB  import tensorflow as tf from tensorflow import keras from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout from tensorflow.keras.optimizers import RMSprop  from django.template.loader import get_template, render_to_string from django.shortcuts import render from django.views.generic import TemplateView from django.views.generic.detail import DetailView from django.views import View from django.db.models import Count from django.shortcuts import redirect  from portal.models import Subscribe  from el_pagination.views import AjaxListView from django.http import Http404, JsonResponse, HttpResponse, HttpResponseRedirect, HttpResponseServerError from django.db.models import Q from django.contrib.staticfiles.templatetags.staticfiles import static

Теперь мы готовы создать функцию, которую я назвал upload_csv, она берёт CSV-файл, загруженный в наши шаблоны, и создаст фрейм данных Pandas. Мы будем делать самые разные вещи с данными этого файла, в зависимости от запросов пользователя. Когда пользователь кликает по опциям фронтенда, мы сохраняем опции в переменной, переменная, в свою очередь, может принимать эти значения:

  • _plot — строим график рассеяния или тепловую карту.
  • _cate — выполняем алгоритм Априори для категориальных переменных.
  • _unsuper — выбираем один алгоритм ML без учителя.
  • _super — выполняем алгоритм с учителем.

Когда мы кликаем по опции, тип контролируемого или неконтролируемого алгоритма хранится в переменной 'algo', затем в зависимости от того, какой тип выбран, мы запускаем другую модель из опций Scikit-Learn, всё это выглядит так: 

def upload_csv(request):	 	if request.method == "POST": 	    file = request.FILES['csv_file'] 	    df = pd.read_csv(file) 	    t = [] 	    names = list(df.head(0)) 	    df_target = df 	    grafica = request.POST['graficas'] 	    if request.POST['submit'] == '_plot':  	        if grafica == "scatter": 		        fig = px.scatter_matrix(df_target) 		        graph_div = plotly.offline.plot(fig, auto_open = False, output_type="div") 		        context = {'graph_div': graph_div} 		        return render (request, "plottings.html", context) 	        if grafica == "heatmap": 		        fig = go.Figure(data=go.Heatmap(z = df.corr(),x=names,y=names)) 		        graph_div = plotly.offline.plot(fig, auto_open = False, output_type="div") 		        context = {'graph_div': graph_div} 		        return render (request, "heatmap.html", context) 	    if request.POST['submit'] == '_cate': 		    h = list(df.head(0)) 		    t.append(list(h)) 		    for i in range(0, len(df)): 			    a = list(df.iloc[i]) 			    t.append(a) 		    itemsets, rules = apriori(t, min_support=0.2,  min_confidence=1) 		    context = {'rules': rules}           	   		    return render(request, "apriori.html", context)	 	    lon = len(list(df.head(0))) 	    header = list(df[0:lon]) 	    target = header[lon-1] 	    y = np.array(df[target]) 	    df.drop(target,axis=1,inplace=True) 	    X = df.values 	    Z = X 	    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,random_state=101)  	    graph_div = '' 	    pred = '' 	    algo = request.POST['algoritmo']	 	    grafica = request.POST['graficas'] 	    clasi = request.POST['clasi'] 	 	    if request.POST['submit'] == '_unsuper': 			    Nc = range(1, 20) 			    kmeans = [KMeans(n_clusters=i) for i in Nc] 			    score = [kmeans[i].fit(Z).score(Z) for i in range(len(kmeans))] 			    fig = go.Figure(data=go.Scatter(y=score, x=list(Nc), mode='markers')) 			    fig.update_xaxes(title="Number of Clusters") 			    fig.update_yaxes(title="Error") 			    fig.update_layout(autosize=False, width=800,height=500) 			    graph = plotly.offline.plot(fig, auto_open = False, output_type="div")            			    nclusters = int(request.POST['clusters']) 			    kmeans = KMeans(n_clusters=nclusters) 			    model = kmeans.fit(Z) 			    labels = kmeans.labels_ 			    resultados = [] 			    for i in labels: 		                    resultados.append(i)	 			    with open('/var/www/trainyourmodel/static/labels.csv', 'w', ) as myfile: 				    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL) 				    for word in resultados: 					    wr.writerow([word])	 			    context = {'graph': graph, 'labels': labels}            			    return render(request, "kmeans.html", context)					 	    if request.POST['submit'] == '_super': 	 		    if algo == 'Linear Regression': 			    lm = LinearRegression() 			    model = lm.fit(X_train,y_train) 			    pred = lm.predict(X_test) 			    mae = metrics.mean_absolute_error(y_test,pred) 			    mse = metrics.mean_squared_error(y_test,pred) 			    rmse = np.sqrt(metrics.mean_squared_error(y_test,pred)) 			    coef = pd.DataFrame(lm.coef_, df.columns, columns=['Coefficient'])	 			    fig = go.Figure(data=go.Scatter(x=y_test, y=pred, mode='markers')) 			    fig.update_xaxes(title="Test Sample") 			    fig.update_yaxes(title="Predictions") 			    fig.update_layout(autosize=False, width=800,height=500) 			    scatter = plotly.offline.plot(fig, auto_open = False, output_type="div") 			    resultados = [] 			    for i in pred: 		                    resultados.append(i)	 			    with open('/var/www/trainyourmodel/static/pred.csv', 'w', ) as myfile: 				    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL) 				    for word in resultados: 					    wr.writerow([word])	 			    context = {'pred':pred, 'scatter': scatter, 'mae': mae, 'mse': mse, 'rmse': rmse, 'coef': coef}            			    return render(request, "scatter.html", context)	 		    if algo == 'Support Vector Machine': 			    param_grid = {'C':[0.1,1,10,100,1000],'gamma':[1,0.1,0.01,0.001,0.0001]} 			    grid = GridSearchCV(SVC(),param_grid,verbose=3) 			    model = grid.fit(X_train,y_train) 			    pred = grid.predict(X_test) 			    mae = metrics.mean_absolute_error(y_test,pred) 			    mse = metrics.mean_squared_error(y_test,pred) 			    rmse = np.sqrt(metrics.mean_squared_error(y_test,pred)) 			    matrix = print(confusion_matrix(y_test,pred)) 			    report = print(classification_report(y_test,pred)) 		    if algo == 'K-Nearest Neighbor': 			    knn = KNeighborsClassifier(n_neighbors=1) 			    model = knn.fit(X_train,y_train) 			    pred = knn.predict(X_test) 			    mae = metrics.mean_absolute_error(y_test,pred) 			    mse = metrics.mean_squared_error(y_test,pred) 			    rmse= np.sqrt(metrics.mean_squared_error(y_test,pred)) 			    matrix = confusion_matrix(y_test,pred) 			    report = classification_report(y_test,pred)	 		    if algo == 'Naive Bayes': 			    gnb = GaussianNB() 			    pred = gnb.fit(X_train, y_train).predict(X_test) 			    mae = metrics.mean_absolute_error(y_test,pred) 			    mse = metrics.mean_squared_error(y_test,pred) 			    rmse = np.sqrt(metrics.mean_squared_error(y_test,pred)) 			    matrix = confusion_matrix(y_test,pred) 			    report = classification_report(y_test,pred)	 		    if algo == 'Decision Trees': 			    dtree = DecisionTreeClassifier() 			    model = dtree.fit(X_train,y_train) 			    pred = dtree.predict(X_test) 			    mae = metrics.mean_absolute_error(y_test,pred) 			    mse = metrics.mean_squared_error(y_test,pred) 			    rmse = np.sqrt(metrics.mean_squared_error(y_test,pred)) 			    matrix = confusion_matrix(y_test,pred) 			    report = classification_report(y_test,pred) 		    if algo == 'Random Forest': 			    forest = RandomForestClassifier(n_estimators=200) 			    model = forest.fit(X_train,y_train) 			    pred = forest.predict(X_test) 			    mae = metrics.mean_absolute_error(y_test,pred) 			    mse = metrics.mean_squared_error(y_test,pred) 			    rmse = np.sqrt(metrics.mean_squared_error(y_test,pred)) 			    matrix = confusion_matrix(y_test,pred)	 			    report = classification_report(y_test,pred)	 		    resultados = [] 		    for i in pred: 			    resultados.append(i)	 		    with open('/var/www/trainyourmodel/static/pred.csv', 'w', ) as myfile: 			    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL) 			    for word in resultados: 			            wr.writerow([word])	 		    context = {'matrix00': matrix[0][0], 'matrix01': matrix[0][1], 'matrix10': matrix[1][0], 'matrix11': matrix[1][1], 'mae': mae, 'mse': mse, 'rmse': rmse, 'f1': report[0:52], 'f2': report[54:106], 'f3': report[107:159], 'f4': report[160:213]}            		    return render(request, "upload_csv.html", context)	

Наконец, если вы нажмёте на кнопку «deep learning» в верхней части сайта, то перейдёте на другой экран, входные данные на этом экране берутся функцией под названием neural, которая будет работать с нейронными сетями. Есть два типа сетей на выбор: «mean-squared-error» или «binary cross-entropy». Как только функция проверяет тип сети для запуска, она берёт эпохи, пакет, значения плотности и выводит на экран модель Keras, показывая точность прогнозов, получается что-то вроде этого:

def neural(request):	 	if request.method == "POST": 	    file = request.FILES['file'] 	    df = pd.read_csv(file) 	    df_target = df 	    lon = len(list(df.head(0))) 	    dim = len(list(df.head(0))) -1	 	    header = list(df[0:lon]) 	    target = header[dim] 	    y = np.array(df[target]) 	    df.drop(target,axis=1,inplace=True) 	    X = df.values 	    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,random_state=101)  	    graph_div = '' 	    pred = '' 	    red = request.POST['red'] 	    dense = int(request.POST['dense'])	 	    epochs = int(request.POST['epochs']) 	    batch = int(request.POST['batch']) 	    #nodes = int(request.POST['categories']) 	    if red == 'Binary Cross-Entropy': 			    model= Sequential() 			    model.add(Dense(dense, input_dim=dim, activation='relu')) 			    model.add(Dense(dim, activation='relu')) 			    model.add(Dense(1, activation='sigmoid')) 			    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) 			    model.fit(x=X_train,y=y_train,batch_size=batch, epochs=epochs,shuffle=True) 			    pred = model.predict(X_test)	 			    _, accuracy = model.evaluate(X_test, y_test)			     			    accu = (accuracy*100) 			    resultados = [] 			    for i in pred: 		                    resultados.append(i[0])	 			    with open('/var/www/trainyourmodel/static/pred.csv', 'w', ) as myfile: 				    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL) 				    for word in resultados: 					    wr.writerow([word])	 			    context = {'accu': accu, 'pred': pred}            			    return render(request, "neural.html", context)						 	    if red == 'Mean Squared Error': 			    model = Sequential() 			    model.add(Dense(dense, input_dim=dim, activation='relu')) 			    model.add(Dense(1, activation='linear')) 			    model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy']) 			    model.fit(x=X,y=y,batch_size=batch, epochs=epochs,shuffle=True) 			    pred = model.predict(X_test) 			    _, accuracy = model.evaluate(X_test, y_test) 			    resultados = [] 			    for i in pred: 		                    resultados.append(i[0])	 			    with open('/var/www/trainyourmodel/static/pred.csv', 'w', ) as myfile: 				    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL) 				    for word in resultados: 					    wr.writerow([word]) 			    accu = (accuracy*100)	 			    context = {'accu': accu, 'pred': pred}            			    return render(request, "neural.html", context)

Заключение

В этом проекте мы увидели, как сравнительно легко внедрить приложение для компьютерного обучения на сервере Linux с помощью Django, мы могли бы также использовать Flask (еще одно популярное приложение на Python) или многие другие технологии. Дело в том, что, если вы просто хотите, чтобы ваша модель работала на фронтенде сайта, чтобы пользователи могли ею пользоваться, вам нужно лишь встроить свои модели в функции, которые принимают входные данные, настроенные пользователями. 

Обратите внимание, что мы делали всё на лету, не нуждаясь в базе данных. Это очень маленький навык, если вы являетесь инженером-машиностроителем и вам необходимо быстро построить и развернуть модель. Проблема с реальными платформами машинного обучения заключается в том, что им необходимо принимать огромные объёмы данных от тысяч пользователей и хранить пользовательскую информацию, то есть проблема этих платформ заключается не в сложности выполняемых ими моделей, а в сложности облачных операций, которые они выполняют, чтобы иметь возможность справляться с их рабочей нагрузкой. Что ж, на сегодня всё, надеюсь, вам понравился этот проект и понравилось программировать его!


Источник: habr.com

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