Интуиция Spark MLlib / K-Means

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

http://databricks.gitbooks.io/databricks-spark-reference-applications/content/twitter_classifier/README.html

В частности, этот код:

http://databricks.gitbooks.io/databricks-spark-reference-applications/content/twitter_classifier/scala/src/main/scala/com/databricks/apps/twitter_classifier/ExamineAndTrain.scala

За исключением того, что я пытаюсь запустить его в пакетном режиме для некоторых твитов, которые он извлекает из Cassandra, в данном случае всего 200 твитов.

Как показывает пример, я использую этот объект для «векторизации» набора твитов:

object Utils{
  val numFeatures = 1000
  val tf = new HashingTF(numFeatures)

  /**
   * Create feature vectors by turning each tweet into bigrams of
   * characters (an n-gram model) and then hashing those to a
   * length-1000 feature vector that we can pass to MLlib.
   * This is a common way to decrease the number of features in a
   * model while still getting excellent accuracy (otherwise every
   * pair of Unicode characters would potentially be a feature).
   */
  def featurize(s: String): Vector = {
    tf.transform(s.sliding(2).toSeq)
  }
}

Вот мой код, модифицированный из ExaminAndTrain.scala:

 val noSets = rawTweets.map(set => set.mkString("\n"))

val vectors = noSets.map(Utils.featurize).cache()
vectors.count()

val numClusters = 5
val numIterations = 30

val model = KMeans.train(vectors, numClusters, numIterations)

  for (i <- 0 until numClusters) {
    println(s"\nCLUSTER $i")
    noSets.foreach {
        t => if (model.predict(Utils.featurize(t)) == 1) {
          println(t)
        }
      }
    }

Этот код запускается, и каждый кластер печатает «кластер 0», «кластер 1» и т. д., а внизу ничего не печатается. если я переверну

models.predict(Utils.featurize(t)) == 1 

to

models.predict(Utils.featurize(t)) == 0

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

Вот что я интуитивно думаю, что происходит (пожалуйста, поправьте мои мысли, если я ошибаюсь): этот код превращает каждый твит в вектор, случайным образом выбирает несколько кластеров, затем запускает kmeans для группировки твитов (на самом высоком уровне кластеры, т.е. предположим, были бы общие "темы"). Таким образом, когда он проверяет каждый твит, чтобы убедиться, что models.predict == 1, в каждом кластере должны появляться разные наборы твитов (и поскольку он проверяет обучающий набор против самого себя, каждый твит должен быть в кластере). Почему это не делается? Либо я неправильно понимаю, что делает kmeans, либо мой тренировочный набор слишком мал, либо я пропустил шаг.

Любая помощь приветствуется


person plamb    schedule 08.03.2015    source источник


Ответы (1)


Ну, во-первых, KMeans — это алгоритм кластеризации, и поэтому он не контролируется. Так что никакой "проверки обучающей выборки против самой себя" (ну ладно, можно и вручную ;).

Ваше понимание на самом деле довольно хорошее, просто вы упускаете момент, когда model.predict(Utils.featurize(t)) дает вам кластер, которому t принадлежит, как назначено KMeans. Я думаю, ты хочешь проверить

models.predict(Utils.featurize(t)) == i

в вашем коде, так как я перебираю все метки кластера.

Также небольшое замечание: вектор признаков создан на основе 2-граммовой модели персонажей твитов. Этот промежуточный шаг важен;)

2-грамма (для слов) означает: «Медведь кричит на медведя» => {(А, медведь), (медведь, кричит), (кричит, на), (на, а), (медведь)}, т.е. «медведь» считается дважды. Символы будут (A, [пробел]), ([пробел], b), (b, e) и так далее.

person uberwach    schedule 08.03.2015
comment
это bigrams of characters, поэтому должно быть {("A ", " b", "be" ...}. - person Thomas Jungblut; 09.03.2015
comment
Спасибо за этот ответ uberwatch. Я внес это изменение, и он напечатал 5 кластеров, за исключением того, что в кластере 0 были все твиты под ним, а в остальных кластерах их не было, что, как я полагаю, означает, что все твиты назначаются кластеру 0. Это потому, что набор данных слишком мал? (Я думаю, что в примере, предоставленном databricks, они обучают модель kmeans примерно 12 миллионам твитов, а я использую только 200). Или нужно настроить numClusters/numIterations? - person plamb; 09.03.2015
comment
Или это потому, что он классифицирует твиты на основе языка (как в примере с блоками данных)? Возможно, все они относятся к кластеру 0, потому что на высоком уровне это английский кластер. Это потому, что он смотрит на биграммы символов? Будет ли просмотр биграмм слов больше похож на просмотр тем в твитах? Если да, то как изменить Utils, чтобы он создавал биграммы слов вместо символов? - person plamb; 09.03.2015
comment
Не обращайте внимания на последний вопрос, я вижу, что HashingTF.transform принимает строку твита, и вы можете манипулировать ею, используя обычные строковые методы. Последний вопрос: есть ли способ увидеть, какие точки были выбраны кластерами? Могу ли я увидеть их вектор, а затем вернуться от вектора к слову (словам), которому он соответствует? - person plamb; 09.03.2015
comment
Я не уверен, правильно ли я понял ваш вопрос, но нет. Хеширование должно быть необратимым. - person uberwach; 10.03.2015