Вы можете найти этот пост и многое другое на моем Веб-сайт !
Цель
К концу этого поста мы узнаем, как использовать Создать ML MLRECommender
Чтобы порекомендовать песню пользователю, учитывая их истории прослушивания. Мы также узнаем, как разбираться и подготовить Mldatatable
Использование Python и Data от третьей стороны.
Введение в MLRECommender.
Персонализированная система рекомендации может использоваться во многих различных приложениях, таких как музыкальный проигрыватель, видеоплеер или сайт социальных сетей. Система рекомендации машинного обучения сравнивает прошлую деятельность пользователя для большой библиотеки активности от многих других пользователей. Например, если Spotify хотел порекомендовать вам новую ежедневную смесь, их система ML ML-рекомендации может посмотреть на историю прослушивания в течение последних нескольких недель и сравнить историю истории ваших друзей. Наша цель сегодня – создать MLRECommender
Рекомендовать песни пользователю, учитывая их истории прослушивания.
Конструктор для MLRECommender
является:
init(trainingData: MLDataTable, userColumn: String, itemColumn: String, ratingColumn: String? = nil, parameters: MLRecommender.ModelParameters = ModelParameters()) throws
Создание таблиц данных
Первый шаг – создать WeatingData
в виде Mldatatable
Отказ В этом случае наши учебные данные – это история прослушивания многих разных пользователей из Миллион наборов песни , который проводит метаданные более миллиона песен и рейтингов, предоставляемых пользователями.
Мы будем использовать два файла из набора данных. Первый это 1000.txt
Содержит идентификатор пользователя, идентификатор песни и время прослушивания для 10000 записей. Мы назовем это History.txt
впредь. Второй – song_data.csv.
, который содержит идентификатор песни, название, дату выпуска и имя исполнителя. Мы назовем это Songs.csv
впредь. Все полные файлы для этого руководства можно найти в конце поста.
Вот как выглядят наши входные файлы. Обратите внимание, что Songs.csv
имеет ряд заголовка, пока History.txt.
не:
# history.txt b80344d063b5ccb3212f76538f3d9e43d87dca9e SOAKIMP12A8C130995 1 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBBMDR12A8C13253B 2 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBXHDL12A81C204C0 1 ...
# songs.csv song_id,title,release,artist_name,year SOQMMHC12AB0180CB8,"Silent Night","Monster Ballads X-Mas","Faster Pussy cat",2003 SOVFVAK12A8C1350D9,"Tanssi vaan","Karkuteillä",Karkkiautomaatti,1995 SOGTUKN12AB017F4F1,"No One Could Ever",Butter,"Hudson Mohawke",2006 ...
Мы будем использовать Пандас Библиотека Python для обработки наших данных CSV. Сначала загрузите файлы выше и назовите их History.txt
и Songs.csv
и мы загрузим их:
import csv import pandas as pd history_file = 'history.txt' # 'https://static.turi.com/datasets/millionsong/10000.txt' songs_metadata_file = 'songs.csv' # 'https://static.turi.com/datasets/millionsong/song_data.csv' # Import the files history_df = pd.read_table(history_file, header=None) history_df.columns = ['user_id', 'song_id', 'listen_count'] metadata_df = pd.read_csv(songs_metadata_file)
Songs.csv
Уже есть заголовки столбцов в файле, поэтому нам не нужно было добавлять такие, как мы сделали с История_df
Отказ Это то, как сейчас выглядят наши данные по датафам:
# history_df user_id song_id listen_count 0 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOAKIMP12A8C130995 1 1 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBBMDR12A8C13253B 2 2 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBXHDL12A81C204C0 1 ...
# metadata_df # (The '\' means that the row continues onto the next lines) song_id title release \ 0 SOQMMHC12AB0180CB8 Silent Night Monster Ballads X-Mas 1 SOVFVAK12A8C1350D9 Tanssi vaan Karkuteillä 2 SOGTUKN12AB017F4F1 No One Could Ever Butter artist_name year 0 Faster Pussy cat 2003 1 Karkkiautomaatti 1995 2 Hudson Mohawke 2006 ...
Далее, чтобы создать одну историю прослушивания для всех пользователей, мы хотим объединить данные песни в metadata_df
в историю прослушивания в История_df
и создать CSV для использования в SWIFT. Давайте также добавим столбец, который сочетает в себе название песни с именем художника, чтобы мы могли видеть как в нашем MLRECommender
:
# Merge the files into a single csv song_df = pd.merge(history_df, metadata_df.drop_duplicates(['song_id']), on="song_id", how="left") song_df.to_csv('merged_listen_data.csv', quoting=csv.QUOTE_NONNUMERIC) # Add a "Title - Name" column for easier printing later song_df['song'] = song_df['title'] + ' - ' + song_df['artist_name']
Вот что теперь выглядит наша комбинированная песня DataFrame:
# song_df user_id song_id listen_count \ 0 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOAKIMP12A8C130995 1 1 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBBMDR12A8C13253B 2 2 b80344d063b5ccb3212f76538f3d9e43d87dca9e SOBXHDL12A81C204C0 1 title release artist_name year \ 0 The Cove Thicker Than Water Jack Johnson 0 1 Entre Dos Aguas Flamenco Para Niños Paco De Lucia 1976 2 Stronger Graduation Kanye West 2007 song 0 The Cove - Jack Johnson 1 Entre Dos Aguas - Paco De Lucia 2 Stronger - Kanye West ...
С момента написания, MLRECommender
требует, чтобы столбец идентификатора элемента в WeatingData
Перейти от 1 до количества предметов. Другими словами, если наше WeatingData
включены только три песни, merged_listen_data.csv
будет иметь такие идентификаторы песни, как Soqmmhc12ab0180cb8
, SUVFVAK12A8C1350D9
и Sogtukn12ab017f4f1
, но нам нужно иметь идентификаторы песни 0
С 1
и 2
Отказ Давайте добавим новый столбец к CSV, который использует инкрементные идентификаторы песни от 0 до N:
# Find the unique song ids song_ids = metadata_df.song_id.unique() # Create a new dataframe of the unique song ids and a new incremental # id for each one incremental_id_df = pd.DataFrame({'song_id': song_ids}) incremental_id_df['incremental_song_id'] = incremental_id_df.index # Merge the original song metadata with the incremental ids new_song_id_df = pd.merge(song_id_df, incremental_id_df, on='song_id', how='left') new_song_id_df.to_csv('songs_incremental_id.csv', quoting=csv.QUOTE_NONNUMERIC) # Create a new merged history and song metadata CSV with incremental ids new_history_df = pd.merge(history_df, incremental_id_df, on='song_id', how='inner') new_history_df.to_csv('merged_listen_data_incremental_song_id.csv', quoting=csv.QUOTE_NONNUMERIC)
Вот как выглядит наша новая песня CSV-файл. Обратите внимание, что в начале есть добавленный столбец с идентификатором песни от 0 до 999999:
# songs_incremental_id.csv "","song_id","title","release","artist_name","year","incremental_song_id" 0,"SOQMMHC12AB0180CB8","Silent Night","Monster Ballads X-Mas","Faster Pussy cat",2003,0 1,"SOVFVAK12A8C1350D9","Tanssi vaan","Karkuteillä","Karkkiautomaatti",1995,1 2,"SOGTUKN12AB017F4F1","No One Could Ever","Butter","Hudson Mohawke",2006,2 ...
И вот как наш окончательный объединенный данные прослушивания выглядит с помощью инкрементных идентификаторов, готовых к чтению MLRECommender
:
# merged_listen_data_incremental_song_id.csv "","Unnamed: 0","user_id","song_id","listen_count","title","release","artist_name","year","incremental_song_id" 0,0,"b80344d063b5ccb3212f76538f3d9e43d87dca9e","SOAKIMP12A8C130995",1,"The Cove","Thicker Than Water","Jack Johnson",0,397069 1,18887,"7c86176941718984fed11b7c0674ff04c029b480","SOAKIMP12A8C130995",1,"The Cove","Thicker Than Water","Jack Johnson",0,397069 2,21627,"76235885b32c4e8c82760c340dc54f9b608d7d7e","SOAKIMP12A8C130995",3,"The Cove","Thicker Than Water","Jack Johnson",0,397069 ...
Теперь мы готовы загрузить его в рекомендации!
Использование MLRECommender.
Создайте новую SWIFT Playground и добавьте два CSV merged_listen_data_incremental_song_id.csv
и songs_incremental_id.csv
как ресурсы на вашей детской площадке. За помощью о добавлении ресурсов на Swift Playground, проверьте Это пост Отказ Убедитесь, что ваша SWIFT Playground является пустой игровой площадкой Macos, а не детская площадка IOS Отказ Потому что наш MLRECommender
Даст нам только идентификатор пользователя и инкрементную песню при создании рекомендаций, мы будем использовать второй CSV для просмотра названий песни.
Во-первых, давайте загрузим объединенную историю прослушивания с помощью инкрементных идентификаторов:
import Foundation import CreateML // Create an MLDataTable from the merged CSV data let history_csv = Bundle.main.url(forResource: "merged_listen_data_incremental_song_id", withExtension: "csv")! let history_table = try MLDataTable(contentsOf: history_csv) print(history_table)
Columns: X1 string Unnamed: 0 integer user_id string song_id string listen_count integer title string release string artist_name string year integer incremental_song_id integer Rows: 2000000 Data: +----------------+----------------+----------------+----------------+----------------+ | X1 | Unnamed: 0 | user_id | song_id | listen_count | +----------------+----------------+----------------+----------------+----------------+ | 0 | 0 | b80344d063b5...| SOAKIMP12A8C...| 1 | | 1 | 18887 | 7c8617694171...| SOAKIMP12A8C...| 1 | | 2 | 21627 | 76235885b32c...| SOAKIMP12A8C...| 3 | | 3 | 27714 | 250c0fa2a77b...| SOAKIMP12A8C...| 1 | | 4 | 34428 | 3f73f44560e8...| SOAKIMP12A8C...| 6 | | 5 | 34715 | 7a4b8e7d2905...| SOAKIMP12A8C...| 6 | | 6 | 55885 | b4a678fb729b...| SOAKIMP12A8C...| 2 | | 7 | 65683 | 33280fc74b16...| SOAKIMP12A8C...| 1 | | 8 | 75029 | be21ec120193...| SOAKIMP12A8C...| 1 | | 9 | 105313 | 6fbb9ff93663...| SOAKIMP12A8C...| 2 | +----------------+----------------+----------------+----------------+----------------+ +----------------+----------------+----------------+----------------+---------------------+ | title | release | artist_name | year | incremental_song_id | +----------------+----------------+----------------+----------------+---------------------+ | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | | The Cove | Thicker Than...| Jack Johnson | 0 | 397069 | +----------------+----------------+----------------+----------------+---------------------+ [2000000 rows x 10 columns]
Оттуда мы можем создать MLRECommender
Отказ Наше WeatingData
Является ли формат таблицы данных объединенного истории прослушивания CSV, Usercolumn
это user_id
Имя столбца и itembolumn
это incrimental_song_id
Имя столбца. user_id
B80344D063B5CCB3212F76538F3D9E43D87DCA9E
был случайным образом выбран из объединенных данных CSV: =.
// Generate recommendations let recommender = try MLRecommender(trainingData: history_table, userColumn: "user_id", itemColumn: "incremental_song_id") let recs = try recommender.recommendations(fromUsers: ["b80344d063b5ccb3212f76538f3d9e43d87dca9e"]) print(recs)
Columns: user_id string incremental_song_id integer score float rank integer Rows: 10 Data: +----------------+---------------------+----------------+----------------+ | user_id | incremental_song_id | score | rank | +----------------+---------------------+----------------+----------------+ | b80344d063b5...| 114557 | 0.0461493 | 1 | | b80344d063b5...| 834311 | 0.0436045 | 2 | | b80344d063b5...| 939015 | 0.043068 | 3 | | b80344d063b5...| 955047 | 0.0427589 | 4 | | b80344d063b5...| 563380 | 0.0426116 | 5 | | b80344d063b5...| 677759 | 0.0423951 | 6 | | b80344d063b5...| 689170 | 0.0418951 | 7 | | b80344d063b5...| 333053 | 0.041788 | 8 | | b80344d063b5...| 381319 | 0.0403042 | 9 | | b80344d063b5...| 117491 | 0.0400819 | 10 | +----------------+---------------------+----------------+----------------+ [10 rows x 4 columns]
Но мы хотим знать метаданные песни, связанные с каждым рекомендуемым incrimental_song_id.
. Давайте загрузим таблицу метаданных песен и присоединиться к рекомендациям с метаданными песни с использованием инкрементного ID:
// Use the songs data CSV to print the recommended song titles let songs_csv = Bundle.main.url(forResource: "songs_incremental_id", withExtension: "csv")! let songs_table = try MLDataTable(contentsOf: songs_csv) print(songs_table) let song_title_recs = recs.join(with: songs_table, on: "incremental_song_id") print(song_title_recs)
Columns: X1 string song_id string title undefined release string artist_name string year integer incremental_song_id integer Rows: 1000000 Data: +----------------+----------------+----------------+----------------+----------------+ | X1 | song_id | title | release | artist_name | +----------------+----------------+----------------+----------------+----------------+ | 0 | SOQMMHC12AB0...| Silent Night | Monster Ball...| Faster Pussy...| | 1 | SOVFVAK12A8C...| Tanssi vaan | Karkuteillä | Karkkiautoma...| | 2 | SOGTUKN12AB0...| No One Could...| Butter | Hudson Mohawke | | 3 | SOBNYVR12A8C...| Si Vos Querés | De Culo | Yerba Brava | | 4 | SOHSBXH12A8C...| Tangle Of As...| Rene Ablaze ...| Der Mystic | | 5 | SOZVAPQ12A8C...| Symphony No....| Berwald: Sym...| David Montgo...| | 6 | SOQVRHI12A6D...| We Have Got ...| Strictly The...| Sasha / Turb...| | 7 | SOEYRFT12AB0...| 2 Da Beat Ch...| Da Bomb | Kris Kross | | 8 | SOPMIYT12A6D...| Goodbye | Danny Boy | Joseph Locke | | 9 | SOJCFMH12A8C...| Mama_ mama c...| March to cad...| The Sun Harb...| +----------------+----------------+----------------+----------------+----------------+ +----------------+---------------------+ | year | incremental_song_id | +----------------+---------------------+ | 2003 | 0 | | 1995 | 1 | | 2006 | 2 | | 2003 | 3 | | 0 | 4 | | 0 | 5 | | 0 | 6 | | 1993 | 7 | | 0 | 8 | | 0 | 9 | +----------------+---------------------+ [1000000 rows x 7 columns] Columns: user_id string incremental_song_id integer score float rank integer X1 string song_id string title undefined release string artist_name string year integer Rows: 11 Data: +----------------+---------------------+----------------+----------------+----------------+ | user_id | incremental_song_id | score | rank | X1 | +----------------+---------------------+----------------+----------------+----------------+ | b80344d063b5...| 114557 | 0.0461493 | 1 | 114578 | | b80344d063b5...| 117491 | 0.0400819 | 10 | 117512 | | b80344d063b5...| 333053 | 0.041788 | 8 | 333174 | | b80344d063b5...| 381319 | 0.0403042 | 9 | 381465 | | b80344d063b5...| 381319 | 0.0403042 | 9 | 444615 | | b80344d063b5...| 563380 | 0.0426116 | 5 | 563705 | | b80344d063b5...| 677759 | 0.0423951 | 6 | 678222 | | b80344d063b5...| 689170 | 0.0418951 | 7 | 689654 | | b80344d063b5...| 834311 | 0.0436045 | 2 | 834983 | | b80344d063b5...| 939015 | 0.043068 | 3 | 939863 | +----------------+---------------------+----------------+----------------+----------------+ +----------------+----------------+----------------+----------------+----------------+ | song_id | title | release | artist_name | year | +----------------+----------------+----------------+----------------+----------------+ | SOHENSJ12AAF...| Great Indoors | Room For Squ...| John Mayer | 0 | | SOOGZYY12A67...| Crying Shame | In Between D...| Jack Johnson | 2005 | | SOGFKJE12A8C...| Sun It Rises | Fleet Foxes | Fleet Foxes | 2008 | | SOECLAD12AAF...| St. Patrick'...| Room For Squ...| John Mayer | 0 | | SOECLAD12AAF...| St. Patrick'...| Room For Squ...| John Mayer | 0 | | SOAYTRA12A8C...| All At Once | Sleep Throug...| Jack Johnson | 2008 | | SOKLVUI12A67...| If I Could | In Between D...| Jack Johnson | 2005 | | SOYIJIL12A67...| Posters | Brushfire Fa...| Jack Johnson | 2000 | | SORKFWO12A8C...| Quiet Houses | Fleet Foxes | Fleet Foxes | 2008 | | SOJAMXH12A8C...| Meadowlarks | Fleet Foxes | Fleet Foxes | 2008 | +----------------+----------------+----------------+----------------+----------------+ [11 rows x 10 columns]
Последняя таблица напечатана наши рекомендуемые песни, а первый – «Великий в помещении»! Теперь мы можем использовать наши MLRECommender
Для других идентификаторов пользователей.
Заворачивать
Во-первых, мы посмотрели на MLRECommender
конструктор. Тогда мы собрали данные песни из миллионов песни набора данных. Мы модифицировали набор данных для увеличения разборчивости и добавлены инкрементные идентификаторы для метаданных песни. Мы загрузили метаданные песни и истории прослушивания в Swift Playground, создали MLRECommender
Из истории прослушивания и созданные рекомендуемые песни. Затем мы использовали песни метаданные, чтобы присоединиться к рекомендуемым песням к своим названиям и артистам.
Исходные файлы
Каждый из файлов, упомянутых в этом руководстве, можно найти здесь , включая:
Songs.csv
: Метаданные на миллион песенHistory.txt
: История прослушивания песни для нескольких пользователейdata-parser.py
: Код Python для манипулирования набора данных Million Songmerged_listed_data.csv
: Объединенный набор данных песни метаданных и истории прослушиванияmerged_listed_data_incremental_song_id.csv.
:merged_listed_data.csv
с добавленными инкрементными идентификаторамиsongs_incremental_id.csv
:Songs.csv
с инкрементными идентификаторами добавленMusicrecommender.playground
: Swift Playground для создания MLRECommender
Этот пост в блоге был вдохновлен Эриком Ле ‘ Как построить простую систему соревновательной песни Отказ
Оригинал: “https://dev.to/nickymarino/how-to-build-a-song-recommender-using-create-ml-mlrecommender-45h1”