Вычисление взаимной информации Для выбора Обучающего набора в Java

StackOverflow https://stackoverflow.com/questions/2002521

Вопрос

Сценарий


Я пытаюсь реализовать контролируемое обучение по набору данных в приложении Java GUI.Пользователю будет предоставлен список элементов или "отчетов" для проверки, и он будет помечать их на основе набора доступных меток.Как только контролируемое обучение будет завершено, помеченные экземпляры будут переданы алгоритму обучения.При этом будет предпринята попытка упорядочить остальные элементы в зависимости от того, насколько вероятно, что пользователь захочет их просмотреть.

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

Пример


Здесь искусственный пример может помочь объяснить и прояснить путаницу, когда я, несомненно, использовал неправильную терминологию :-) Рассмотрим пример, в котором приложение отображает пользователю новости.Он выбирает, какие новости отображать в первую очередь, на основе показанных предпочтений пользователя.Особенностями новостного сюжета, которые имеют корреляцию, являются country of origin, category или date.Таким образом, если пользователь помечает одну новость как интересную, когда она пришла из Шотландии, это говорит специалисту по машинному обучению, что повышается вероятность того, что другие новости из Шотландии будут интересны пользователю.Аналогично для такой категории, как Спорт, или для такой даты, как 12 декабря 2004 года.

Это предпочтение может быть рассчитано путем выбора любого порядка для всех новостных сюжетов (напримерпо категориям, по дате) или произвольно упорядочивая их, затем вычисляя предпочтения по мере продвижения пользователя.Что я хотел бы сделать, так это получить своего рода "фору" в этом упорядочении, предложив пользователю просмотреть небольшое количество конкретных новостей и сказать, заинтересованы ли они в них (часть контролируемого обучения).Чтобы выбрать, какие истории показывать пользователю, я должен рассмотреть всю коллекцию историй.Вот тут-то и пригодится Взаимная информация.Для каждой истории я хочу знать, как много она может рассказать мне обо всех других историях, когда она классифицируется пользователем.Например, если существует большое количество историй, происходящих из Шотландии, я хочу заставить пользователя классифицировать (по крайней мере) одну из них.Аналогично для других коррелирующих характеристик, таких как категория или дата.Цель состоит в том, чтобы найти примеры отчетов, которые, будучи классифицированными, предоставляют наибольшую информацию о других отчетах.

Проблема


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

mutual information equation

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

Как и в моем примере, допустим, у меня было большое количество новых, немаркированных экземпляров этого класса:

public class NewsStory {
    private String countryOfOrigin;
    private String category;
    private Date date;
    // constructor, etc.
}

В моем конкретном сценарии корреляция между полями / функциями основана на точное совпадение так, например, разница в дате в один день и 10 лет эквивалентны по своему неравенству.

Факторы для корреляции (например,является ли дата более коррелирующей, чем категория?) не обязательно равны, но они могут быть предопределенными и постоянными.Означает ли это, что результат выполнения функции p(x,y) является предопределенное значение, или я путаю термины?

Этот Вопрос (наконец-то)


Как я могу приступить к реализации взаимного расчета информации, учитывая этот (поддельный) пример новостных сюжетов?Библиотеки, javadoc, примеры кода и т.д.это вся желанная информация.Кроме того, если этот подход в корне ошибочен, объяснение, почему это так, было бы столь же ценным ответом.


PS.Я знаю о таких библиотеках, как Weka и Apache Mahout, поэтому простое упоминание о них для меня не очень полезно.Я все еще просматриваю документацию и примеры для обеих этих библиотек в поисках материалов, конкретно касающихся взаимной информации.Что действительно помогло бы мне, так это указать на ресурсы (примеры кода, javadoc), где эти библиотеки помогают обмениваться информацией.

Это было полезно?

Решение

Я предполагаю, что ваша проблема заключается в чем-то подобном...

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

Если это так, я не думаю, что взаимная информация - это правильная вещь для использования, потому что вы не можете вычислить MI между двумя экземплярами.Определение MI дано в терминах случайных величин, а отдельный экземпляр не является случайной величиной, это просто значение.

Объекты и метка класса могут рассматриваться как случайные величины.То есть они имеют распределение значений по всему набору данных.Вы можете вычислить взаимную информацию между двумя объектами, чтобы увидеть, насколько "избыточным" один объект наделен другим, или между объектом и меткой класса, чтобы получить представление о том, насколько этот объект может помочь в прогнозировании.Именно так люди обычно используют взаимную информацию в задаче контролируемого обучения.

Я думаю, что предложение Фердисченко о том, чтобы вы посмотрели на активные методы обучения, является хорошим.


В ответ на комментарий Грундлефлека я немного углублюсь в терминологию, используя его идею аналогии с объектом Java...

В совокупности мы использовали термины "экземпляр", "вещь", "отчет" и "пример" для обозначения классифицируемого объекта.Давайте думать об этих вещах как об экземплярах класса Java (я опустил шаблонный конструктор).:


class Example
{ String f1;
  String f2;
}

Example e1 = new Example("foo", "bar");
Example e2 = new Example("foo", "baz");

Обычная терминология в машинном обучении заключается в том, что e1 - это пример, что все примеры имеют два возможности f1 и f2 и что для e1 f1 принимает значение 'foo', а f2 принимает значение 'bar'.Коллекция примеров называется набор данных.

Возьмите все значения f1 для всех примеров в наборе данных, это список строк, его также можно рассматривать как распределение.Мы можем думать об этой функции как о случайная величина и что каждое значение в списке является выборкой, взятой из этой случайной величины.Таким образом, мы можем, например, вычислить MI между f1 и f2.Псевдокод был бы чем-то вроде:

mi = 0
for each value x taken by f1:
{  sum = 0
   for each value y taken by f2:
   {  p_xy = number of examples where f1=x and f2=y
      p_x = number of examples where f1=x
      p_y = number of examples where f2=y
      sum += p_xy * log(p_xy/(p_x*p_y))
   }
   mi += sum
}

Однако вы не можете вычислить MI между e1 и e2, это просто не определено таким образом.

Другие советы

Я знаю прирост информации только в связи с деревьями решений (DTS), где при построении DT разделение, которое необходимо произвести на каждом узле, максимизирует прирост информации.DTS реализованы в Weka, так что вы, вероятно, могли бы использовать это напрямую, хотя я не знаю, позволяет ли Weka вам вычислять прирост информации для какого-либо конкретного разделения под узлом DT.

Кроме того, если я вас правильно понимаю, я думаю, что то, что вы пытаетесь сделать, обычно называют активное обучение.Там вам сначала понадобятся некоторые начальные помеченные обучающие данные, которые будут переданы вашему алгоритму машинного обучения.Затем ваш классификатор помечает набор немаркированных экземпляров и возвращает доверительные значения для каждого из них.Экземпляры с наименьшими значениями достоверности обычно являются наиболее информативными, поэтому вы показываете их человеку-аннотирующему, и он / она помечает их вручную, добавляет их в ваш обучающий набор, переобучает ваш классификатор и проделывает все это снова и снова, пока ваш классификатор не достигнет достаточно высокой точности или пока не будет выполнен какой-либо другой критерий остановки.Так что, если это работает для вас, вы могли бы в принципе использовать любой ML-алгоритм, реализованный в Weka или любом другом ML-фреймворке, при условии, что выбранный вами алгоритм способен возвращать доверительные значения (в случае байесовских подходов это были бы просто вероятности).


С вашим отредактированным вопросом, я думаю, я начинаю понимать, к чему вы стремитесь.Если то, что вы хотите, это вычисление MI, то ответ StompChicken и псевдокод, на мой взгляд, не могут быть намного понятнее.Я также думаю, что MI - это не то, чего вы хотите, и что вы пытаетесь заново изобрести колесо.

Давайте резюмируем:вы хотели бы обучить классификатор, который может быть обновлен пользователем.Это классический пример активного обучения.Но для этого вам нужен начальный классификатор (в принципе, вы могли бы просто предоставить пользователю случайные данные для пометки, но я так понимаю, это не вариант), и для того, чтобы обучить ваш начальный классификатор, вам нужно хотя бы небольшое количество помеченных обучающих данных для контролируемого обучения.Однако все, что у вас есть, - это немаркированные данные.Что вы можете с этим сделать?

Ну, ты мог бы кластер их в группы связанных экземпляров, используя один из стандартных алгоритмов кластеризации, предоставляемых Weka, или какой-либо конкретный инструмент кластеризации, такой как Клуто.Если теперь вы возьмете x наиболее центральных экземпляров каждого кластера (x в зависимости от количества кластеров и терпения пользователя) и попросите пользователя пометить их как интересные или неинтересные, вы можете применить этот ярлык и к другим экземплярам этого кластера (или, по крайней мере, к центральным).Вуаля, теперь у вас есть обучающие данные, которые вы можете использовать для обучения вашего начального классификатора и запуска активного процесса обучения, обновляя классификатор каждый раз, когда пользователь отмечает новый экземпляр как интересный или нет.Я думаю, что то, чего вы пытаетесь достичь, вычисляя MI, по сути аналогично, но может быть просто неправильной кареткой для вашей зарядки.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top