Вас интересует машинное обучение и его приложения? Если вы хотите узнать что-то новое и интересное, как насчет системы рекомендаций по машинному обучению?

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

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

Ответ почти все.

Все, что может сделать человек, модель машинного обучения может сделать лучше.

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

Все, что может сделать человек, модель машинного обучения может сделать лучше; учитывая время и усилия.

Достаточно хорошо про ML против человека, давайте поговорим о том, что мы здесь делаем. Итак, здесь мы будем создавать систему рекомендаций по машинному обучению.

Что такое система рекомендаций по машинному обучению ?

Система рекомендаций - это модель машинного обучения, которая рекомендует новые варианты выбора и учитывает ваши предыдущие действия по теме. Это означает, что модель поймет ваш выбор и порекомендует варианты, которые вам «могут понравиться». Возможно, вы видели товары, рекомендованные Spotify, Netflix или Amazon. Это похоже на это, но, возможно, менее эффективно.

Что именно мы собираемся порекомендовать?

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

Все (почти все) любят настраиваемые темы для своей IDE или текстовых редакторов и тратят много времени на поиск тем, которые они хотели бы использовать.

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

Как бы это выглядело?

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

Давайте теперь перейдем к коду. Для создания этой модели мы будем использовать JavaScript, CSS и HTML вместе с библиотекой машинного обучения «brain.js».

Полный код можно найти в этом репозитории GitHub.

Теперь мы обсудим код JavaScript, который мы используем для работы этой модели. Сначала давайте напишем код для создания экземпляров некоторых переменных, библиотек и кода, которые будут составлять пользовательский интерфейс для нашей веб-страницы.

const editorWrapper = document.querySelector(".editor-wrapper")
const colorOne = document.querySelectorAll(".color-1")
const colorTwo = document.querySelectorAll(".color-2")
const colorThree = document.querySelectorAll(".color-3")
const stars = document.querySelectorAll(".star")
const themes = document.getElementById("themes")

window.localStorage.trainingData = window.localStorage.trainingData || JSON.stringify([])


// our current voting combination
const currentColors = {
  back: {},
  one: {},
  two: {},
  three: {},
}

Это некоторые из тех переменных, которые мы будем использовать для изменения цвета текста и темы текста на нашей веб-странице.

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

// kick it off by creating a random theme for you to vote on
/* 
  as you vote, saveTrainingData
  - saves to localstorage
  - runs predictThemeCombinations
*/
/*
  predictThemeCombinations
  - trains a neural network from your vote history
  - creates 100,000 random themes
  - runs the themes through the network, getting a score for each
  - sorts and returns the top 20 scored themes
*/   
generateRandomTheme()
predictThemeCombinations()

Мы напишем код для generateRandomTheme() и predictThemeCombinations() позже.

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

stars.forEach((star, i) => {
  const score = i / 4
  star.addEventListener("mouseenter", setStars.bind(setStars, i))
  star.addEventListener("mouseleave", clearStars)
  star.addEventListener("click", saveTrainingData.bind(saveTrainingData, score))
})

Мы также будем писать код для функций setStars() и clearStars().

Теперь давайте напишем код функции saveTrainingData() для оценки, которую получает пользователь, оценивая тему. Этот метод сохраняет данные обучения в соответствии с оценкой и использует их для обучения нашей модели.

function saveTrainingData(score) {
  const data = JSON.parse(window.localStorage.trainingData)

  data.push({
    input: [
      Math.round(currentColors.back.r/2.55) / 100, // divide by 255 and round to 2 decimal places
      Math.round(currentColors.back.g/2.55) / 100,
      Math.round(currentColors.back.b/2.55) / 100,
      Math.round(currentColors.one.r/2.55) / 100,
      Math.round(currentColors.one.g/2.55) / 100,
      Math.round(currentColors.one.b/2.55) / 100,
      Math.round(currentColors.two.r/2.55) / 100,
      Math.round(currentColors.two.g/2.55) / 100,
      Math.round(currentColors.two.b/2.55) / 100,
      Math.round(currentColors.three.r/2.55) / 100,
      Math.round(currentColors.three.g/2.55) / 100,
      Math.round(currentColors.three.b/2.55) / 100,
    ],
    output: [score]
  })

  window.localStorage.trainingData = JSON.stringify(data)


  predictThemeCombinations()
  clearStars()
  generateRandomTheme()
}

Здесь мы также использовали метод clearStars(), который в основном удаляет звездный рейтинг со страницы, если пользователь не нажимал на нее, и убирает курсор.

Метод setStars() делает именно то, что мы обсуждали ранее.

function setStars(whichStar) {
  for (let i = 0; i < stars.length; i++) {
    stars[i].classList.add("gold")
    if (i >= whichStar) {
      break;
    }
  }
}

function clearStars() {
  for (const star of stars) {
    star.classList.remove("gold")
  }
}

Теперь давайте напишем код для generateRandomTheme(), который мы использовали в самом начале веб-страницы. Этот метод просто получает случайный цвет фона и 3 других случайных цвета для установки темы на первое время e.

function generateRandomTheme() {
  currentColors.back = getRandomBackgroundRgb()
  currentColors.one = getRandomRgb()
  currentColors.two = getRandomRgb()
  currentColors.three = getRandomRgb()

  editorWrapper.style.background = `rgb(${currentColors.back.r},${currentColors.back.g},${currentColors.back.b})`
  for (let color of colorOne) {
    color.style.color = `rgb(${currentColors.one.r},${currentColors.one.g},${currentColors.one.b})`
  }
  for (let color of colorTwo) {
    color.style.color = `rgb(${currentColors.two.r},${currentColors.two.g},${currentColors.two.b})`
  }
  for (let color of colorThree) {
    color.style.color = `rgb(${currentColors.three.r},${currentColors.three.g},${currentColors.three.b})`
  }
}

И дополнительные методы (функции, если вы их называете), которые мы использовали выше.

function getRandomRgb() {
  return {
    r: Math.round(Math.random()*205 + 50), // number between 50 and 255
    g: Math.round(Math.random()*205 + 50),
    b: Math.round(Math.random()*205 + 50),
  }
}

function getRandomBackgroundRgb() {
  return {
    r: Math.round(Math.random()*50), // number between 0 and 50
    g: Math.round(Math.random()*50),
    b: Math.round(Math.random()*50),
  }
}

И метод, который все это делает. Функция predictThemeCombinations() использует обученную сеть, обученную по истории, чтобы получить цвета и темы, которые им, вероятно, понравятся. Найдите время, чтобы понять, как работает этот метод. Это просто, но умно.

function predictThemeCombinations() {
  const data = JSON.parse(window.localStorage.trainingData)
  if (!data.length) {
    return;
  }

  themes.innerHTML = ""
  const net = new brain.NeuralNetwork({activation: "leaky-relu"});
  const results = []

  net.train(data)

  for (let i = 0; i < 100000; i++) {
    const back = getRandomBackgroundRgb()
    const one = getRandomRgb()
    const two = getRandomRgb()
    const three = getRandomRgb()
    const colors = [
      Math.round(back.r/2.55) / 100, // divide by 255 and round to 2 decimal places
      Math.round(back.g/2.55) / 100,
      Math.round(back.b/2.55) / 100,
      Math.round(one.r/2.55) / 100,
      Math.round(one.g/2.55) / 100,
      Math.round(one.b/2.55) / 100,
      Math.round(two.r/2.55) / 100,
      Math.round(two.g/2.55) / 100,
      Math.round(two.b/2.55) / 100,
      Math.round(three.r/2.55) / 100,
      Math.round(three.g/2.55) / 100,
      Math.round(three.b/2.55) / 100,
    ]

    const [ score ] = net.run(colors)
    results.push({ back, one, two, three, score})
  }

Кроме того, у нас есть 100 000 результатов, и мы не хотим просто показывать пользователю первый из них. Лучше всего взять 20 лучших рекомендаций. Поэтому мы просто сортируем результаты и показываем из них 20 лучших результатов.

// sort results
  const sortedResults = results.sort(function(a, b) {
    var a = a.score
    var b = b.score

    return b - a
  })

  // keep the top 20 results after sorting
  for (let i = 0; i < 20; i++) {
    addNewTheme(sortedResults[i])
  }
}

addNewTheme()? Что ж, этот метод также будет содержать много HTML и будет немного уродливым. Но по сути, мы просто используем цветовые темы в компонентах HTML, используя это.

function addNewTheme({back, one, two, three, score}) {
  const newTheme = document.createElement("div")
  newTheme.classList.add("predicted-theme")
  newTheme.innerHTML = `
  <div class="editor-wrapper" style="background:rgb(${back.r}, ${back.g}, ${back.b})">
    <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">import</span> React <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">from</span> <span style="color: rgb(${two.r}, ${two.g}, ${two.b})">"react"</span><br/>
    <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">import</span> ReactDOM <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">from</span> <span style="color: rgb(${two.r}, ${two.g}, ${two.b})">"react-dom"</span><br/>
    <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">import {</span> Provider <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">} from</span> <span style="color: rgb(${two.r}, ${two.g}, ${two.b})">"react-redux"</span><br/>
    <br/>
    <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">import</span> Layout <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">from</span> <span style="color: rgb(${two.r}, ${two.g}, ${two.b})">"./components/Layout"</span><br/>
    <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">import</span> store <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">from</span> <span style="color: rgb(${two.r}, ${two.g}, ${two.b})">"./store"</span><br/>
    <br/>
    <span style="color:rgb(${one.r}, ${one.g}, ${one.b})">const</span> app<span style="color:rgb(${one.r}, ${one.g}, ${one.b})"> = </span>document.<span style="color: rgb(${three.r}, ${three.g}, ${three.b})">getElementById</span><span style="color:rgb(${one.r}, ${one.g}, ${one.b})">(</span><span style="color: rgb(${two.r}, ${two.g}, ${two.b})">'app'</span><span style="color:rgb(${one.r}, ${one.g}, ${one.b})">)</span><br/>
    <br/>
    ReactDOM.render<span style="color:rgb(${one.r}, ${one.g}, ${one.b})">(</span>&lt;<span style="color: rgb(${three.r}, ${three.g}, ${three.b})">Provider store={</span>store<span style="color: rgb(${three.r}, ${three.g}, ${three.b})">}</span>&gt;<br/>
    &nbsp;&nbsp;&lt;<span style="color: rgb(${three.r}, ${three.g}, ${three.b})">Layout </span>/&gt;<br/>
    &lt;/<span style="color: rgb(${three.r}, ${three.g}, ${three.b})">Provider</span>&gt;, app<span style="color:rgb(${one.r}, ${one.g}, ${one.b})"">)</span>
  </div>
  <li>Score ${score}</li>
  <li>Background rgb(${back.r}, ${back.g}, ${back.b})</li>
  <li>Color 1 rgb(${one.r}, ${one.g}, ${one.b})</li>
  <li>Color 2 rgb(${two.r}, ${two.g}, ${two.b})</li>
  <li>Color 3 rgb(${three.r}, ${three.g}, ${three.b})</li>
  `
  themes.appendChild(newTheme)
}

Я сказал немного некрасиво? Ну что тут сказать ...

И поверьте мне, этот метод ничего не делает, кроме как устанавливает цвета, которые мы попадаем в наш список 20 лучших, и настраивает их в компонентах.

Опять же, полный код можно найти в этом репозитории GitHub.

Итак, в двух словах

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

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

И результат?

Если мы встречаемся здесь впервые, Я Прадьюман Диксит, я в основном пишу о Машинном обучении, разработке под Android, а иногда и о веб-разработке. .

Вы можете прочитать другие мои сообщения Машинное обучение здесь:

Как создать простой веб-сайт с машинным обучением с нуля

Как понять машинное обучение на простых примерах кода