Также посмотрите 100 сквозных проектов машинного обучения с веб-сайтами

Введение

В этом сообщении блога мы рассмотрим процесс создания сквозного проекта машинного обучения. Мы начнем с получения набора данных из Kaggle, затем предварительно обработаем данные и обучим модель машинного обучения. Наконец, мы развернем модель как веб-приложение с помощью Flask.

Получение данных из Kaggle

Kaggle — популярная платформа, на которой размещаются различные наборы данных для машинного обучения. Чтобы получить данные из Kaggle, нам сначала нужно создать учетную запись на Kaggle и присоединиться к соревнованию или найти интересующий набор данных.

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

Предварительная обработка данных

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

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

Обучение модели машинного обучения

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

Мы будем использовать косинусное подобие для нашего проекта. Он используется для расчета расстояния между векторами.

После обучения модели мы сериализуем модель с помощью библиотеки pickle. Pickle — это библиотека, которая позволяет нам сохранять объекты Python в двоичном формате. Мы сохраним обученную модель в виде файла, чтобы позже загрузить ее в наше приложение Flask.

Создание приложения Flask

Flask — это популярный веб-фреймворк для Python, который позволяет нам быстро и легко создавать веб-приложения. Мы будем использовать Flask для создания веб-приложения, которое берет входное изображение и предсказывает класс изображения с помощью обученной модели.

Наше приложение Flask будет иметь два маршрута: домашний маршрут и прогнозируемый маршрут. На домашнем маршруте будет отображаться простая HTML-страница с формой для загрузки изображения. Маршрут прогнозирования возьмет загруженное изображение, предварительно обработает изображение и сделает прогноз с использованием обученной модели. Результат прогноза будет отображаться на новой странице.

Комплексная система рекомендаций по машинному обучению

Заключение

В этом сообщении блога мы рассмотрели процесс создания сквозного проекта машинного обучения. Мы начали с получения набора данных от Kaggle, затем предварительно обработали данные и обучили модель машинного обучения. Наконец, мы развернули модель как веб-приложение с помощью Flask.

Код проекта можно найти ниже.

Код блокнота:

import numpy as np
 import pandas as pd
movie = pd.read_csv('tmdb_5000_movies.csv')
 credits = pd.read_csv("tmdb_5000_credits.csv")
movie.head()
credits.head()
merging both dataset
movies = movie.merge(credits, on='title')
movies.head()
keeping important columns
[8]
movies.columns
Index(['budget', 'genres', 'homepage', 'id', 'keywords', 'original_language',
 'original_title', 'overview', 'popularity', 'production_companies',
 'production_countries', 'release_date', 'revenue', 'runtime',
 'spoken_languages', 'status', 'tagline', 'title', 'vote_average',
 'vote_count', 'movie_id', 'cast', 'crew'],
 dtype='object')
movies = movies[['id','title','overview','keywords','genres','cast','crew']]
movies
checking null vals
[11]
movies.isnull().sum()
id 0
 title 0
 overview 3
 keywords 0
 genres 0
 cast 0
 crew 0
 dtype: int64
[12]
moveis.dropna(inplace=True)
working with overview `
[13]
movies.iloc[0].overview
'In the 22nd century, a paraplegic Marine is dispatched to the moon Pandora on a unique mission, but becomes torn between following orders and protecting an alien civilization.'
[14]
# it is a string so convert is into list
 movies['overview'] = movies['overview'].apply(lambda x:x.split())
[15]
movies['overview'][0]
['In',
 'the',
 '22nd',
 'century,',
 'a',
 'paraplegic',
 'Marine',
 'is',
 'dispatched',
 'to',
 'the',
 'moon',
 'Pandora',
 'on',
 'a',
 'unique',
 'mission,',
 'but',
 'becomes',
 'torn',
 'between',
 'following',
 'orders',
 'and',
 'protecting',
 'an',
 'alien',
 'civilization.']
working with keywords
[16]
movies['keywords'][0]
'[{"id": 1463, "name": "culture clash"}, {"id": 2964, "name": "future"}, {"id": 3386, "name": "space war"}, {"id": 3388, "name": "space colony"}, {"id": 3679, "name": "society"}, {"id": 3801, "name": "space travel"}, {"id": 9685, "name": "futuristic"}, {"id": 9840, "name": "romance"}, {"id": 9882, "name": "space"}, {"id": 9951, "name": "alien"}, {"id": 10148, "name": "tribe"}, {"id": 10158, "name": "alien planet"}, {"id": 10987, "name": "cgi"}, {"id": 11399, "name": "marine"}, {"id": 13065, "name": "soldier"}, {"id": 14643, "name": "battle"}, {"id": 14720, "name": "love affair"}, {"id": 165431, "name": "anti war"}, {"id": 193554, "name": "power relations"}, {"id": 206690, "name": "mind and soul"}, {"id": 209714, "name": "3d"}]'
[17]
import ast # use to convert string to integer
 def keywords(obj):
 l = []
 for i in ast.literal_eval(obj):
 l.append(i['name'])
 return l
[18]
movies['keywords'] = movies['keywords'].apply(keywords)
[19]
movies['keywords']
0 [culture clash, future, space war, space colon…
 1 [ocean, drug abuse, exotic island, east india …
 2 [spy, based on novel, secret agent, sequel, mi…
 3 [dc comics, crime fighter, terrorist, secret i…
 4 [based on novel, mars, medallion, space travel…
 … 
 4804 [united states–mexico barrier, legs, arms, pap…
 4805 []
 4806 [date, love at first sight, narration, investi…
 4807 []
 4808 [obsession, camcorder, crush, dream girl]
 Name: keywords, Length: 4806, dtype: object
working with genres
[20]
movies['genres'][0]
'[{"id": 28, "name": "Action"}, {"id": 12, "name": "Adventure"}, {"id": 14, "name": "Fantasy"}, {"id": 878, "name": "Science Fiction"}]'
[21]
import ast # use to convert string to integer
 def genres(obj):
 l = []
 for i in ast.literal_eval(obj):
 l.append(i['name'])
 return l
[22]
movies['genres'] = movies['genres'].apply(genres)
[23]
movies['genres']
0 [Action, Adventure, Fantasy, Science Fiction]
 1 [Adventure, Fantasy, Action]
 2 [Action, Adventure, Crime]
 3 [Action, Crime, Drama, Thriller]
 4 [Action, Adventure, Science Fiction]
 … 
 4804 [Action, Crime, Thriller]
 4805 [Comedy, Romance]
 4806 [Comedy, Drama, Romance, TV Movie]
 4807 []
 4808 [Documentary]
 Name: genres, Length: 4806, dtype: object
working with cast
[24]
movies['cast'][0]
'[{"cast_id": 242, "character": "Jake Sully", "credit_id": "5602a8a7c3a3685532001c9a", "gender": 2, "id": 65731, "name": "Sam Worthington", "order": 0}, {"cast_id": 3, "character": "Neytiri", "credit_id": "52fe48009251416c750ac9cb", "gender": 1, "id": 8691, "name": "Zoe Saldana", "order": 1}, {"cast_id": 25, "character": "Dr. Grace Augustine", "credit_id": "52fe48009251416c750aca39", "gender": 1, "id": 10205, "name": "Sigourney Weaver", "order": 2}, {"cast_id": 4, "character": "Col. Quaritch", "credit_id": "52fe48009251416c750ac9cf", "gender": 2, "id": 32747, "name": "Stephen Lang",
import ast # use to convert string to integer
 def cast(obj):
 l = []
 # intersted in top three cast
 count = 0
 for i in ast.literal_eval(obj):
 if count != 3:
 l.append(i['name'])
 count+=1
 else:
 break
 return l
 
 movies['cast'] = movies['cast'].apply(cast)
[26]
movies['cast']
0 [Sam Worthington, Zoe Saldana, Sigourney Weaver]
 1 [Johnny Depp, Orlando Bloom, Keira Knightley]
 2 [Daniel Craig, Christoph Waltz, Léa Seydoux]
 3 [Christian Bale, Michael Caine, Gary Oldman]
 4 [Taylor Kitsch, Lynn Collins, Samantha Morton]
 … 
 4804 [Carlos Gallardo, Jaime de Hoyos, Peter Marqua…
 4805 [Edward Burns, Kerry Bishé, Marsha Dietlein]
 4806 [Eric Mabius, Kristin Booth, Crystal Lowe]
 4807 [Daniel Henney, Eliza Coupe, Bill Paxton]
 4808 [Drew Barrymore, Brian Herzlinger, Corey Feldman]
 Name: cast, Length: 4806, dtype: object
working with crew
[27]
movies['crew'][0]
'[{"credit_id": "52fe48009251416c750aca23", "department": "Editing", "gender": 0, "id": 1721, "job": "Editor", "name": "Stephen E. Rivkin"}, {"credit_id": "539c47ecc3a36810e3001f87", "department": "Art", "gender": 2, "id": 496, "job": "Production Design", "name": "Rick Carter"}, {"credit_id": "54491c89c3a3680fb4001cf7", "department": "Sound", "gender": 0, "id": 900, "job":
import ast # use to convert string to integer
 def crew(obj):
 l = []
 # interested in top three cast
 count = 0
 for i in ast.literal_eval(obj):
 if i['job'] == 'Director':
 l.append(i['name'])
 break
 return l
[29]
movies['crew'] = movies['crew'].apply(crew)
[30]
movies['crew']
0 [James Cameron]
 1 [Gore Verbinski]
 2 [Sam Mendes]
 3 [Christopher Nolan]
 4 [Andrew Stanton]
 … 
 4804 [Robert Rodriguez]
 4805 [Edward Burns]
 4806 [Scott Smith]
 4807 [Daniel Hsia]
 4808 [Brian Herzlinger]
 Name: crew, Length: 4806, dtype: object
concatenating last four cols into one`
[31]
movies['tags'] = movies['overview'] + movies['cast'] + movies['crew'] + movies['keywords']
[32]
movies = movies[['id','title','tags']]
[33]
movies
removing spaces form tags
[34]
movies['tags'] = movies['tags'].apply(lambda x: [i.replace(" ", "") for i in x])
A value is trying to be set on a copy of a slice from a DataFrame.
 Try using .loc[row_indexer,col_indexer] = value instead
 
 See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
 movies['tags'] = movies['tags'].apply(lambda x: [i.replace(" ", "") for i in x])
[35]
movies['tags'][0]
['In',
 'the',
 '22nd',
 'century,',
 'a',
 'paraplegic',
 'Marine',
 'is',
 'antiwar',
 'powerrelations',
 'mindandsoul',
 '3d']
applying stemming
[36]
from nltk.stem.porter import PorterStemmer
 ps = PorterStemmer()
[37]
movies['tags']
0 [In, the, 22nd, century,, a, paraplegic, Marin…
 1 [Captain, Barbossa,, long, believed, to, be, d…
 2 [A, cryptic, message, from, Bond's, past, send…
 3 [Following, the, death, of, District, Attorney…
 4 [John, Carter, is, a, war-weary,, former, mili…
 … 
 4804 [El, Mariachi, just, wants, to, play, his, gui…
 4805 [A, newlywed, couple's, honeymoon, is, upended…
 4806 ["Signed,, Sealed,, Delivered", introduces, a,…
 4807 [When, ambitious, New, York, attorney, Sam, is…
 4808 [Ever, since, the, second, grade, when, he, fi…
 Name: tags, Length: 4806, dtype: object
[38]
def stemming(text):
 l = []
 for i in text:
 l.append(ps.stem(i))
 return " ".join(l)
[39]
movies['tags'] = movies['tags'].apply(stemming)
A value is trying to be set on a copy of a slice from a DataFrame.
 Try using .loc[row_indexer,col_indexer] = value instead
[40]
movies['tags'][10]
'superman return to discov hi 5-year absenc ha allow lex luthor to walk free, and that those he wa closest too felt abandon and have move on. luthor plot hi ultim reveng that could see million kill and chang the face of the planet forever, as well as rid himself of the man of steel. brandonrouth kevinspacey katebosworth bryansing savingtheworld dccomic invulner sequel superhero basedoncomicbook kryptonit superpow superhumanstrength lexluthor'
Vectorization code
[41]
from sklearn.feature_extraction.text import CountVectorizer
 vectorizer = CountVectorizer(max_features=500, stop_words='english')
[42]
vectors = vectorizer.fit_transform(movies['tags']).toarray()
[43]
vectors
array([[1, 0, 0, …, 0, 0, 0],
 [0, 0, 0, …, 0, 0, 0],
 [0, 0, 0, …, 0, 0, 0],
 …,
 [0, 0, 0, …, 0, 0, 0],
 [0, 0, 0, …, 1, 0, 0],
 [0, 0, 0, …, 0, 0, 0]], dtype=int64)
['3d',
 'accident',
 'act',
 'action',
 'adventur',
 'affair',
 'aftercreditssting',
 'age',
 'agent',
 'alcohol',
 'alien',
 'alway',
 'young',
 'zombi']
Calculating distances
[45]
from sklearn.metrics.pairwise import cosine_similarity
[46]
similarity = cosine_similarity(vectors)
[47]
movies[movies['title']=="Avatar"]
[48]
sorted(list(enumerate(similarity[0])),reverse=True,key=lambda x:x[1])
[(0, 0.9999999999999998),
 (507, 0.50709255283711),
 (151, 0.46188021535170054),
 (1216, 0.44262666813799045),
 (539, 0.38729833462074165),
 (1321, 0.36514837167011066),
 (1920, 0.3544587784792833),
 (305, 0.3464101615137754),
 (2786, 0.3450327796711771),
 (1774, 0.3442651863295481),
 
 …]
movies.iloc[100].title
'The Curious Case of Benjamin Button'
[50]
def Recommendation_system(movie):
 movie_index = movies[movies['title']== movie].index[0]
 distances = sorted(list(enumerate(similarity[0])),reverse=True,key=lambda x:x[1])
 
 for i in distances[1:20]:
 print(movies.iloc[i[0]].title)
[51]
Recommendation_system('Avatar')
Independence Day
 Beowulf
 Aliens vs Predator: Requiem
 Titan A.E.
 The Thing
 Lifeforce
 Treasure Planet
 Attack the Block
 Martian Child
 Edge of Tomorrow
 Predators
 Meet Dave
 Capricorn One
 Tears of the Sun
 Under the Skin
 Independence Daysaster
 Lockout
 Aliens in the Attic
 E.T. the Extra-Terrestrial
Pickling files
[53]
import pickle
 pickle.dump(movies, open('model.pkl','wb'))
 pickle.dump(similarity, open('similarity','wb'))

Код Flask;

from flask import Flask, request, render_template
import requests
import pandas as pd
import pickle
app = Flask(__name__)
# loading models
# movies = pd.read_csv('movies.csv')
movies = pickle.load(open('model.pkl', 'rb'))
similarity = pickle.load(open('similarity.pkl', 'rb'))
# function to fetch movie poster
def fetch_poster(movie_id):
    url = "https://api.themoviedb.org/3/movie/{}?api_key=390e76286265f7638bb6b19d86474639&language=en-US".format(movie_id)
    data = requests.get(url)
    data = data.json()
    full_path = "https://image.tmdb.org/t/p/w500/" + data['poster_path']
    return full_path
# function to get recommended movies
def get_recommendations(movie):
    # get the index of the selected movie
    idx = movies[movies['title'] == movie].index[0]
    # get pairwise similarity scores of all movies with the selected movie
    sim_scores = list(enumerate(similarity[idx]))
    # sort the movies based on similarity scores in descending order
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
    # get top 20 similar movies (excluding the selected movie)
    sim_scores = sim_scores[1:21]
    # get titles and posters of the recommended movies
    movie_indices = [i[0] for i in sim_scores]
    movie_titles = movies['title'].iloc[movie_indices].tolist()
    movie_posters = [fetch_poster(movies['id'].iloc[i]) for i in movie_indices]
    return movie_titles, movie_posters
# home page
@app.route('/')
def home():
    movie_list = movies['title'].tolist()
    return render_template('index.html', movie_list=movie_list)
# recommendation page
@app.route('/recommend', methods=['POST'])
def recommend():
    movie_title = request.form['selected_movie']
    recommended_movie_titles, recommended_movie_posters = get recommendations(movie_title)
    return render_template('index.html', movie_list=movies['title'].tolist(),
                           recommended_movie_titles=recommended_movie_titles,
                           recommended_movie_posters=recommended_movie_posters)
if __name__ == '__main__':
    app.run(debug=True)

HTML-код:

<!doctype html>
<html>
    <head>
        <title>Movie Recommender</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    </head>
    <body style="background:#D9F799">
        <div style="color:white; margin-top:15px; border-radius:20px;" class="container my-3 mt-3 bg-dark">
            <h1 class="text-center">Movie Recommendation System</h1>
            <form action="/recommend" method="POST">
                <div class="form-group">
                    <label for="movie-select">Select a movie:</label>
                    <select class="form-control" id="movie-select" name="selected_movie">
                        {% for movie in movie_list %}
                            <option value="{{ movie }}">{{ movie }}</option>
                        {% endfor %}
                    </select>
                </div>
                <button type="submit" class="btn btn-primary">Get Recommendations</button>
            </form>
       {% if movie_list %}
    <h2>Recommended Movies:</h2>
    <div class="row">
        {% for i in range(recommended_movie_titles|length) %}
            <div class="col-md-3">
                <div class="card mb-3">
                    <img src="{{ recommended_movie_posters[i] }}" class="card-img-top" alt="...">
                    <div class="card-body">
                        <h5 class="card-title">{{ recommended_movie_titles[i] }}</h5>
                    </div>
                </div>
            </div>
        {% endfor %}
    </div>
{% endif %}
        </div>
        <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    </body>
</html>