Spark MLlib / K-означава интуиция

Аз съм много нов в алгоритмите за машинно обучение и 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 за групиране на туитовете (на наистина високо ниво, клъстерите, i предположим, ще бъдат общи „теми“). По този начин, когато проверява всеки туит, за да види дали 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
Или защото класифицира туитовете въз основа на език (както е в примера с databricks)? Може би всички те са причислени към клъстер 0, защото това на високо ниво е английският клъстер. Дали това е защото разглежда биграми от знаци? Дали разглеждането на биграми от думи би било по-сходно с разглеждането на теми в туитовете? Ако е така, как да модифицирам Utils, за да създава биграми от думи вместо знаци? - person plamb; 09.03.2015
comment
Няма значение за последния въпрос, виждам, че HashingTF.transform приема низа на туит и можете да го манипулирате, като използвате общи методи за низове. Последен въпрос, има ли начин да се види кои точки са избрани от клъстерите? Мога ли да видя техния вектор, след което да премина от вектора обратно към думата(ите), на които съответства? - person plamb; 09.03.2015
comment
Не съм сигурен дали разбирам правилно въпроса ви, но не. Предполага се, че хеширането е необратимо. - person uberwach; 10.03.2015