tag:blogger.com,1999:blog-80267477025329693762024-03-18T08:03:08.620+05:00Теория обобщающей способности алгоритмов машинного обучения - ТОСАМОТеория и практика алгоритмов машинного обучения, обладающих обобщающей способностьюAnonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-8026747702532969376.post-55068065143740732982015-01-05T02:02:00.003+05:002015-01-05T02:02:32.191+05:00Полное описание теории обобщающей способности завершено<div dir="ltr" style="text-align: left;" trbidi="on">
Сегодня завершил полное описание теории обобщающей способности.<br />
<br />
Краткий список вопросов на которые теория даёт ответы:<br />
<br />
<ol style="text-align: left;">
<li>Почему максимальная обучающая способность не не всегда соответствует максимальной обобщающей способности?</li>
<li>Как отличить информативные факторы от неинформативных?</li>
<li>Что делать, если решение неоднозначно?</li>
<li>Как получить неизменное качество классификации при наличии
инвариантных искажений информации в выборке и каковы допустимые пределы
инвариантности?</li>
<li>Где и в каких случаях искать причины низкой обобщающей способности: в выборке или в алгоритме?</li>
</ol>
Текст с полным описанием и небольшим примером в формате PDF можно скачать через торрент: <a href="http://rutracker.org/forum/viewtopic.php?t=4906858" rel="nofollow" target="_blank">http://rutracker.org/forum/viewtopic.php?t=4906858</a> <br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-26792459398322139372014-12-31T16:37:00.004+05:002014-12-31T16:37:56.566+05:00Реализация векторной машины на основе библиотеки libVMR<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
На данный момент реализована библиотека <a href="http://libvmr.sourceforge.net/" rel="nofollow" target="_blank">libVMR</a> на Java для решения стандартной задачи машинного обучения в области бинарной классификации: <br /><br /><ul>
<li>Имеется выборка с примерами и ответами на них. </li>
<li>Необходимо по выборке получить адекватную модель бинарной классификации.</li>
</ul>
</div>
Структура векторной машины выглядит так:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-xTEddxDBEg8/VKPe9dfvCuI/AAAAAAAAADM/PYlD9zPAL4s/s1600/vmr_diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-xTEddxDBEg8/VKPe9dfvCuI/AAAAAAAAADM/PYlD9zPAL4s/s1600/vmr_diagram.png" height="640" width="443" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<ol>
<li>Первоначально информация, из которой необходимо будет построить модель для бинарного классификатора, храниться в файле в <a href="https://sites.google.com/site/libvmr/home/release/fajly-v-formate-csv">формате CSV</a>.</li>
<li>C помощью <a href="https://sites.google.com/site/libvmr/home/release/parser">Парсера</a>
можно выбрать файл и преобразовать его в двумерный числовой массив, где
строки массива - это примеры, а ячейки каждой строки - объясняющие
переменные (начальные ячейки) и одна независимая переменная (последняя
ячейка)</li>
<li>Двумерный массив с числовыми данными подается на вход векторной машины VMR</li>
<ol>
<li>Сначала массив поступает в <a href="https://sites.google.com/site/libvmr/home/release/separator">Сепаратор</a>, задачей которого разбить строки на две части: обучающую и контрольную.</li>
<li>Обучающая часть выборки передаётся в <a href="https://sites.google.com/site/libvmr/home/release/normsetting">Нормировщик</a>, целью которого преобразовать все числа к диапазону от -1 до 1 включительно.</li>
<li>Нормированные данные поступают в <a href="https://sites.google.com/site/libvmr/home/release/kernel-trick">Ядерную машину</a>, где из различных комбинаций объясняющих переменных происходит формирование членов для полинома математической модели.</li>
<li>В
конечном итоге, члены полинома передаются Векторной машине, задачей
которой является подбор коэффициентов для них. В результате чего, на
выходе векторной машины получается математическая модель бинарного
классификатора в виде готового полинома</li>
</ol>
<li>Однако полученная в
векторной машине модель не вовсе не обязательно будет пригодной для
прикладного применения. Чтобы проверить её на пригодность, необходимо
выяснить обобщающую способность модели, Для этой цели предусмотрен
Тестер. Тестер берёт модель и проверяет её результативность на
контрольной части выборки, ранее полученной путем разделения общих
данных в Сепараторе.</li>
</ol>
Одно дело создать библиотеку для каких нибудь методов машинного
обучения, другое дело ей воспользоваться. Чтобы было проще пользоваться
библиотекой libVMR, не прибегая к программированию, необходимо создать
какой нибудь юзабельный интерфейс, способный решать задачи с помощью
библиотеки.<br /><br />Собственно решение задачи бинарной классификации делится на несколько этапов:<br /><br />1. Выбор предметной области, в рамках которой будут проводиться исследования.<br />2. Сбор информации — генеральная выборка<br />3.
Анализ информации — машинное обучение с целью построения модели на
одной части выборки (обучающая часть) с последующей проверкой на второй
части выборки (контрольная часть).<br />4. Принятие решения о том,
подходит ли построенная модель для прикладного решения задачи или
необходимо продолжить исследования в данной области.<br /><br />Для того, чтобы решать задачу по п. 3 и п. 4, необходим инструмент. Его реализация указана ниже.<br /><br />Имея собранные согласно п. 2, информационные данные для решаемой задачи размещаются в электронной таблице в формате CSV.<br /><br />После
того, как приложение с графическим интерфейсом запущено, можно
загрузить информацию в приложение, воспользовавшись пунктом меню <b>File > Open</b>.
После загрузки данных, сразу же запускается процесс предобработки и
машинного обучения — построения модели на одной части выборки. После
завершения построения модели, она проверяется на второй части выборки и
выдаются характеристики обобщающей способности (The quality of
modeling): чувствительность(Sensitivity of generalization ability),
специфичность (Specificity of generalization ability) и обобщающая
способность (Generalization ability) в процентах.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-LnJcNf5q0n4/VKPfsYpsVSI/AAAAAAAAADU/f7TQRwrhnio/s1600/guivmr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-LnJcNf5q0n4/VKPfsYpsVSI/AAAAAAAAADU/f7TQRwrhnio/s1600/guivmr.png" height="195" width="400" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Если характеристики обобщающей способности модели являются подходящими
для решения задачи, то готовую модель можно записать в текстовый файл,
воспользовавшись пунктом меню <b>File > Save model</b>. Сама модель
будет записана в файл в виде формул: нормирования входных данных и
формулы принятия решения, где зависимая переменная обозначена, как y.
Если значение в формуле принятия решения больше нулевого, то
распознаваемый объект принадлежит к классу в выборке со значением
зависимой переменной помеченной единицей. Если значение в формуле
принятия решения меньше нулевого, то объект принадлежит к классу со
значением в выборке значением зависимой переменной помеченной нулём. </div>
<br />
<div class="separator" style="clear: both; text-align: left;">
Скачать свежую версию скомпилированного JAR архива для запуска
графического приложения, а также исходные коды библиотеки и приложения
можно на сайте: <a href="http://libvmr.sourceforge.net/" rel="nofollow">http://libvmr.sourceforge.net/</a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: right;">
Юрий Решетов </div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-86048633703275461682014-12-10T20:31:00.000+05:002014-12-10T20:35:08.249+05:00VMR supplant SVM<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
At the moment, the most common implementation for an one artificial neuron learning used by support vector machine — SVM by Vladimir Vapnik. SVM's algorithm find a minimum of structural risk. In order to obtain the nonlinearity of input vectors in SVM used kernel tricks, but very carefully. Incorrectly chosen kernel tricks can cause overfitting.<br />
<a name='more'></a><br />
<br />
But for SVM already have a worthy competitor. This is vector machine by Reshetov – VMR. VMR well as SVM can teach one artificial neuron and also uses kernel tricks to obtain non-linearity of input vectors.<br />
<br />
But the difference VMR that the algorithm searches for the minimax structural risk. Another characteristic difference - a higher generalization ability compared to SVM. Therefore, VMR can use various kernel tricks without risk of overfitting. during training of neuron. Redundant kernel tricks in VMR can automatically redused.<br />
<br />
None of binary classification algorithm in Weka was unable to give the best results on the generalization ability when compared to the VMR. Testing was conducted on samples taken from the repository <a href="http://archive.ics.uci.edu/ml/datasets.html">http://archive.ics.uci.edu/ml/datasets.html</a><br />
<br />
It is possible that VMR finally replaced SVM?<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
If you are not using WMR, then download <a href="https://code.google.com/p/libvmr/" rel="nofollow" target="_blank">HERE</a> the library libvmr, to get unlimited opportunities for machine learning</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-11608801970042433312014-12-09T01:13:00.001+05:002014-12-09T01:19:51.245+05:00Машинное обучение с оппонентом<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Метод инвариантности, т. е. приведение к единому классу обучающей выборки для задач классификации, не обобщает, а всего лишь облегчает задачу последующего обобщения. <br />
<br />
Также нам уже известно, что задачу классификации можно представить в виде системы линейных неравенств. <br />
<br />
Возникает естественный вопрос, каким методом решать эту самую систему? Вроде бы напрашиваются очевидные ответы: линейным или квадратичным программированием. Ведь эти методы и предназначены для систем линейных неравенств? Кстати, квадратичное программирование используется в машине опорных векторов.<br />
<br />
Но такой ответ был бы неверным. Потому что в этом случае мы бы не обобщили, а всего лишь построили самую оптимистичную модель, наиболее склонную к переобучению.<br />
<br />
Почему?<br />
<br />
Ответ неочевиден. Давайте попробуем без всяких математических формул разобраться на каком нибудь аналогичном примере, демонстрирующем, как обучается и переобучается человек?<br />
<br />
Предположим, что мы имеем некоего человека, который является водителем автотранспортного средства. Предположим, что нашему водителю необходимо всякий раз преодолевать некую трассу, соединяющую два пункта: отправления - А и назначения - Б. Предположим, что целью будет засчитываться минимизация времени на преодоление расстояния от пункта А до пункта Б. Предположим, что на трассе могут быть различные препятствия: крутые повороты, проводиться ремонтные работы, имеются ухабы, в некоторых местах люди или животные пытаются перейти дорогу, покрытие дороги может быть как иметь хорошее сцепление, так и не иметь его — гололедица, имеются перекрёстки, присутствуют дорожные знаки и т. д. и т. п. Т..е. имеем условия, как и на любой другой реальной дорожной трассе.<br />
<br />
Если наш водитель будет многократно ездить от пункта А до пункта Б, то рано или поздно он переобучится. Почему не обучится, а именно переобучится? Дело в том, что когда человек что-то многократно вызубривает, то он запоминает некоторые признаки, способствующие улучшению памяти, но не имеющие отношения к предмету обучения. В более наглых случаях он не только запоминает, но и записывает на какие нибудь, например, бумажные носители такую информацию — шпаргалки, чтобы впоследствии ими воспользоваться.<br />
<br />
Если водитель уже многократно проезжал по одной и той же трассе, то он запомнил много различных шпаргалок, которые никакого отношения к дорожному движению не имеют, т. к. не находятся на дорожном покрытии и не являются дорожными знаками или другими автотранспортными средствами. Шпаргалками в этом случае являются различные, хорошо визуально различимые объекты расположенные вдоль обочины. Это самые настоящие шпаргалки, которые даже записывать нет необходимости, т. к. уже где-то расположены и прекрасно видимы. С помощью этих шпаргалок водитель начинает не только лучше ориентироваться, но и получает более высокие прогнозные способности. Например, увидев возле обочины раскидистый дуб, он уже заранее знает, что далее последует крутой поворот вправо и необходимо притормозить, хотя сам поворот находится вне пределов видимости. Или разглядев на обочине другой хорошо запоминающийся объект, может заранее предположить, что впереди особых препятствий не предвидится, а потому можно прибавить скорость. <br />
<br />
Вполне понятно, что если наш водитель будет вынужден проехать по какой либо незнакомой ему доселе трассе, то все прежние шпаргалки ему уже не пригодятся. т. е. он перестанет обращать внимание на то, что расположено вдоль обочины дороги, все объекты там будут только отвлекать внимание, а сосредоточится на видимой части дороги, автотранспортных средствах, которые движутся по трассе, дорожных знаках и т. д. Более того, он будет ехать по незнакомой трассе более осторожно, потому что при отсутствии шпаргалок прогнозирующие способности также отсутствуют: ориентироваться в незнакомой местности можно только по видимым объектам и узнать что будет впереди за пределами зрительных возможностей не получится. <br />
<br />
А теперь возьмём алгоритм машинного обучения, который решает задачу, минимизируя эмпирический риск. Вполне понятно, что алгоритм, как и человек попросту вызубрит не только те признаки которые отвечают решению задачи, но и шпаргалки, т. е. незначимые для решения задачи факторы, но помогающие ему обладать повышенными прогнозирующими способностями. Если переобученному таким образом алгоритму дать выборку с примерами, которые ранее в процессе обучения не встречались, но в той или иной степени похожи, то в отличие от человека, компьютер не сможет определиться, что он имеет дело с другой выборкой и по прежнему будет интерпретировать незначимые факторы, предполагая, что с помощью них он сможет «предсказать» результат, который по его мнению, вроде бы должен является «решением». И попадёт впросак, т. е. начнёт давать неверные ответы.<br />
<br />
Если такой алгоритм переобучить на какой нибудь трассе вождению транспортного средства на автопилоте, то на любой другой трассе, он бы начал вести себя неадекватно, т. е. прибавлять скорость, там где нужно притормаживать и притормаживать, там где отсутствуют видимые препятствия. В результате чего такое «вождение» приведёт, как минимум, к провоцированию аварийных ситуаций и, как максимум, закончится дорожно-транспортным происшествием.<br />
<br />
Теоретически суть вроде бы понятна. Чтобы алгоритм обобщал только то, что значимо, т. е. относится к задаче, необходимо:<br />
<br />
<ol style="text-align: left;">
<li>Снизить ему возможность для зубрёжки, т. е. оградить от возможности воспользоваться шпаргалками для построения модели </li>
<li>Вынудить принимать более осторожные решения.</li>
</ol>
<br />
Если алгоритмы, склонные к переобучению, именовались, как обучающиеся с учителем, хотя там конечно же никакого учителя не было, то алгоритмы с обобщающей способностью именуются обучающимися с оппонентом.<br />
<br />
Как работает такой алгоритм обучения с оппонентом:<br />
<br />
<ol style="text-align: left;">
<li>Алгоритм выдвигает некую гипотезу, т. е. слегка изменяет весовой коэффициент искусственного нейрона для какого нибудь одного фактора</li>
<li>Оппонент предъявляет алгоритму пример из обучающей выборки, наименее соответствующий последней выдвинутой гипотезе.</li>
<li>Алгоритм слегка корректирует весовой коэффициент для одного из факторов таким образом, чтобы улучшить гипотезу для всех ранее предъявленных оппонентом примеров.</li>
<li>Возврат к п. 2.</li>
</ol>
<div style="text-align: left;">
<br />
Такой алгоритм называется минимаксной стратегией и его эффективность доказана теоремой фон Неймана — Моргенштерна (Математическая теория некооперативных антагонистических игр для двух лиц с нулевой суммой).<br />
<br />
Суть в том, что оппонент будет предъявлять алгоритму только те примеры, с которыми тот справляется хуже всего. Вполне понятно, что в таком случае, примеры, на которых алгоритм мог бы переобучиться, т. е. воспользоваться шпаргалками для выдвижения наиболее смелых гипотез, в число предъявляемых не попадут. А поскольку, будут предъявляться только те примеры, для которых необходимы наиболее скромные гипотезы, то переобучение сведётся к минимуму.</div>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-4606292116125634502014-12-07T12:28:00.001+05:002014-12-07T12:37:38.297+05:00Инвариантность - основа обобщающей способности<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Ранее были опубликованы основные методы, необходимые для предварительной обработки информации в нейрокомпьютинге, такие, как разделение выборки на обучающую и тестовую части, нормирование входов и ядерные преобразования.<br />
<br />
Но всё, это уже давно известно, задолго до появления алгоритмов машинного обучения обладающих обобщающей способностью и применялось в нейрокомпьютинге для алгоритмов склонных к переобучению.<br />
<br />
Далее уже будем разбирать основы теории обобщающей способности и подробные разъяснения принципов создания алгоритмов, соответствующих её положениям.<br />
<br />
Инвариантность является основой теории обобщающей способности. Если прежние алгоритмы искали некую гиперплоскость, с помощью которой пытались решить задачу классификации, отделив с её помощью классы друг от друга с целью найти их различия, то инвариантность предполагает совершенно иной подход к решению тех же самых задач: не отделять классы друг от друга, а с помощью инварианта объединить их в один класс с целью найти общие признаки. В этом и заключается основная суть теории обобщающей способности алгоритмов машинного обучения: не искать различия (что разъединяет), а обобщать, т. е. искать то что обобщает.<br />
<br />
Математический смысл инвариантности основан на том, что если правую и левую часть неравенства умножить на некую отрицательную константу, то знак неравенства изменится на противоположный. При этом само неравенство останется истинным:<br />
<br />
<div style="text-align: center;">
A > B</div>
<div style="text-align: center;">
-A < -B</div>
<br />
Все задачи, решаемые с помощью нейрокомпьютинга, можно представить в виде решения системы линейных неравенств — обучающей выборки:<br />
<br />
<div style="text-align: center;">
a11 * w1 + a12 * w2 + … + a1n * wn Z y1</div>
<div style="text-align: center;">
a21 * w1 + a22 * w2 + … + a2n * wn Z y2</div>
<div style="text-align: center;">
…</div>
<div style="text-align: center;">
am1 * w1 + am2 * w2 + … + amn * wn Z ym</div>
<br />
где:<br />
<br />
aij – значение j-го фактора (предиктора - объясняющей переменной) для i-го примера в диапазоне от -1 до 1 включительно<br />
wj – значение j-го весового коэффициента<br />
yi – значение зависимой переменной для i-го примера в диапазоне от -1 до 1 включительно<br />
Z – знак неравенства, принимающий значения: больше, если yi > 0 и меньше, если yi < 0<br />
<br />
Поскольку, в данной задаче известны все значения кроме весовых коэффициентов wj, то решением (результатом обучения в нейрокомпьютинге) будет поиск значений весовых коэффициентов.<br />
<br />
Но мы можем изменить систему линейных неравенств таким образом, чтобы сама система стала инвариантной, но при этом оставалась по прежнему истинной:<br />
<br />
<div style="text-align: center;">
(a11 * w1 + a12 * w2 + … + a1n * wn) / y1 > Const</div>
<div style="text-align: center;">
(a21 * w1 + a22 * w2 + … + a2n * wn) / y2 > Const</div>
<div style="text-align: center;">
…</div>
<div style="text-align: center;">
(am1 * w1 + am2 * w2 + … + amn * wn) / ym > Const</div>
<br />
где:<br />
<br />
Const – некое константное значение, одинаковое для всех уравнений системы<br />
<br />
Соответственно, если в прежней системе неравенств знак неравенства указывал на принадлежность к одному из двух классов (задача бинарной классификации), то в результате применения инвариантности, мы получили ту же самую систему линейных неравенств, в которой имеется всего один единственный класс. <br />
<br />
Чтобы проще понять, зачем это делается, лучше привести какой нибудь простенький пример. Возьмём задачу К. Нелора о классификации трёх объектов: птицы, планера и самолёта и представим их признаки в диапазоне от -1 до 1.<br />
<br />
Птица:<br />
<br />
Крылья = 1<br />
Хвост = 1<br />
Клюв = 1<br />
Оперение = 1<br />
Двигатель = -1<br />
Шасси = -1<br />
<br />
Планер:<br />
<br />
Крылья = 1<br />
Хвост = 1<br />
Клюв = -1<br />
Оперение = -1<br />
Двигатель = -1<br />
Шасси = 1<br />
<br />
Самолёт:<br />
<br />
Крылья = 1<br />
Хвост = 1<br />
Клюв = -1<br />
Оперение = -1<br />
Двигатель = 1<br />
Шасси = 1<br />
<br />
Предположим, что нам нужно создать бинарный классификатор, отличающий объект птица от объектов птицей не являющихся. В этом случае мы имеем два класса объектов:<br />
<br />
<ol style="text-align: left;">
<li>Птица</li>
<li>Планер и Самолёт</li>
</ol>
<div style="text-align: left;">
<br />
Выполним инвариант для второго класса, т. е. для планера и самолёта:<br />
<br />
НЕ Планер:<br />
<br />
Крылья = -1<br />
Хвост = -1<br />
Клюв = 1<br />
Оперение = 1<br />
Двигатель = 1<br />
Шасси = -1<br />
<br />
НЕ Самолёт:<br />
<br />
Крылья = -1<br />
Хвост = -1<br />
Клюв = 1<br />
Оперение = 1<br />
Двигатель = -1<br />
Шасси = -1<br />
<br />
Найдём общие признаки для объектов Птица, НЕ Планер и НЕ самолёт. Ими являются признаки: клюв и оперение. Остальные признаки можно удалить, как незначимые, т. е. понизить размерность. <br />
<br />
Таким образом, приведя с помощью инвариантности объекты разных классов к единому, мы можем обнаружить общие признаки и игнорировать различия, т. е. обобщать и понижать размерность для различий.<br />
<br />
Код на Java:</div>
</div>
<hr />
<pre> /**
* Инвариантное преобразование выборки в результате чего два бинарных класса после преобразования становятся одним общим классом
* @param sample выборка для инварианта
* @return инвариантная выборка
*/
private double[][] getInvariant(double[][] sample) {
double[][] result = new double[sample.length][sample[0].length];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[0].length; j++) {
result[i][j] = sample[i][j] / this.ideals[i];
}
}
return result;
}
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com2tag:blogger.com,1999:blog-8026747702532969376.post-68373092886441254692014-12-07T11:20:00.000+05:002014-12-07T11:20:25.842+05:00Получение результатов обученного нейрона<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Поскольку ранее уже были опубликованы коды методов для нормирования входных данных, а также классы для ядерных преобразований, то теперь самое время опубликовать код метода, с помощью которого будут выводиться результаты обученного бинарного классификатора при предъявлении ему какого нибудь паттерна.<br />
<br />
Код на Java:<br />
<br />
<br /></div>
<hr />
<pre> private KernelTrick trick = null;
/**
* Весовые коэффициенты нейронной сети
*/
private double[] weights = null;
/**
* Получение результатов обученного искусственного нейрона
* @param pattern ненормированные входные значения для предъявления нейрону </pre>
<pre> * @return результат
*/
public double getDecision(double[] pattern) {
double[] sample = new double[this.maxs.length];
for (int i = 0; i < sample.length; i++) {
sample[i] = this.convertToRange(pattern[i], this.maxs[i], this.mins[i]);
if (sample[i] > 1d) {
sample[i] = 1d;
}
if (sample[i] < -1d) {
sample[i] = -1d;
}
}
sample = this.trick.getTransformData(sample);
double result = 0d;
for (int i = 0; i < sample.length; i++) {
result = result + sample[i] * this.weights[i];
}
return result;
}
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-17943118708523884142014-12-07T11:06:00.000+05:002014-12-07T11:06:21.926+05:00Сложное полиноминальное ядерное преобразование<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Данное ядерное преобразование более сложно, т.к. в нём используются сомножители всех возможных сочетаний входных значений.<br />
<br />
Код на Java:<br />
<br />
<br /></div>
<hr />
<pre>package libvmr;
/**
* Сложное полиминальное ядерное преобразование
* @author Yury V. Reshetov
* @version 1.0
*/
public class BigKernelTrick implements KernelTrick{
/**
* Идентификаторы используемых переменных
*/
private String[] variables = null;
/**
* Возвращает идентификаторы используемых переменных
* @return идентификаторы переменных
*/
public String[] getVariables() {
return this.variables;
}
/**
* Преобразовать двумерный массив
* @return
*/
public double[][] getTransformData(double[][] samples, double[] results) {
int count = 1;
for (int i = 0; i < (samples[0].length); i++) {
count = count * 2;
}
double[][] result = new double[samples.length][count];
this.variables = new String[count];
for (int i = 0; i < samples.length; i++) {
for (int j = 0; j < count; j++) {
this.variables[j] = "";
double pp = 1d;
int z = j;
for (int n = 0; n < samples[0].length; n++) {
if ((z % 2) == 1) {
pp = pp * samples[i][n];
this.variables[j] = this.variables[j] + " * x" + n;
}
z = z / 2;
}
result[i][j] = pp;
}
}
return result;
}
/**
* Преобразовать одномерный массив
* @return
*/
public double[] getTransformData(double[] sample) {
int count = 1;
for (int i = 0; i < (sample.length); i++) {
count = count * 2;
}
double[] result = new double[count];
for (int i = 0; i < count; i++) {
double pp = 1d;
int z = i;
for (int n = 0; n < sample.length; n++) {
if ((z % 2) == 1) {
pp = pp * sample[n];
}
z = z / 2;
}
result[i] = pp;
}
return result;
}
}
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-20508665380211454442014-12-06T10:58:00.000+05:002014-12-06T14:54:14.830+05:00Парное ядерное преобразование<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Парное ядерное преобразование расширяет простое ядерное преобразование добавляя произведения пар входных значений. Т.е. добавлены квадраты входных значений, а также различные попарные комбинации их произведений.<br />
<br />
Код парного ядерного преобразования на Java:</div>
<hr />
<pre>package libvmr;
/**
* Парное ядерное преобразование
* @author Yury V. Reshetov
* @version 1.0
*/
public class PairKernelTrick implements KernelTrick {
private String[] variables = null;
/**
* Возвращает идентификаторы используемых переменных
*
* @return идентификаторы переменных
*/
public String[] getVariables() {
return this.variables;
}
/**
* Преобразовать двумерный массив данных
*
* @return преобразованный массив
*/
public double[][] getTransformData(double[][] samples, double[] results) {
String[] tempvariables = new String[samples[0].length + 1];
tempvariables[0] = "";
for (int i = 0; i < samples[0].length; i++) {
tempvariables[i + 1] = " * x" + i;
}
double tempresult[][] = new double[samples.length][samples[0].length + 1];
for (int i = 0; i < samples.length; i++) {
tempresult[i][0] = 1d;
for (int j = 0; j < samples[0].length; j++) {
tempresult[i][j + 1] = samples[i][j];
}
}
this.variables = new String[(samples[0].length + 1) * (samples[0].length + 2) / 2];
int n = 0;
for (int i = 0; i < (samples[0].length + 1); i++) {
for (int j = 0; j < (samples[0].length + 1); j++) {
if (j >= i) {
this.variables[n] = tempvariables[i] + tempvariables[j];
n++;
}
}
}
double result[][] = new double[samples.length][this.variables.length];
for (int k = 0; k < samples.length; k++) {
n = 0;
for (int i = 0; i < (samples[0].length + 1); i++) {
for (int j = 0; j < (samples[0].length + 1); j++) {
// Проверка наличия дубликатов
if (j >= i) {
result[k][n] = tempresult[k][i] * tempresult[k][j];
n++;
}
}
}
}
return result;
}
/**
* Преобразовать одномерный массив
*
* @return одномерный массив
*/
public double[] getTransformData(double[] sample) {
double tempresult[] = new double[sample.length + 1];
for (int i = 0; i < sample.length; i++) {
tempresult[0] = 1d;
for (int j = 0; j < sample.length; j++) {
tempresult[j + 1] = sample[j];
}
}
double result[] = new double[(sample.length + 1) * (sample.length + 2) / 2];
int n = 0;
for (int i = 0; i < (sample.length + 1); i++) {
for (int j = 0; j < (sample.length + 1); j++) {
// Проверка наличия дубликатов
if (j >= i) {
result[n] = tempresult[i] * tempresult[j];
n++;
}
}
}
return result;
}
}
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-25983175296577191732014-12-05T23:48:00.001+05:002014-12-05T23:48:50.202+05:00Простое ядерное преобразование<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Данное ядерное преобразование практически ничего не делает, если не считать, что добавляет пороговое значение. Все остальные данные попросту передаются на входы искусственного нейрона без изменений. <br />
<a name='more'></a><br />
<br />
Такое ядро необходимо когда у в выборке имеется большое количество объясняющих переменных, которые проблематично преобразовать с помощью нелинейных ядерных преобразований, т. к. может не хватить памяти компьютера. В этом случае, после автоматического понижения размерности входов, можно будет узнать, какие объясняющие переменные являются значимыми. Впрочем, если применять нелинейные ядерные преобразования, то значимость тех или иных предикторов может кардинально измениться за счёт того, что степени свободы для поиска минимакса эмпирического риска значительно возрастут.<br />
<br />
Код класса для простого ядерного преобразования на Java:</div>
<hr />
<pre>/**
*
*/
package libvmr;
/**
* Простое ядерное преобразование
* @author Yury V. Reshetov
* @version 1.0
*/
public class SimpleKernelTrick implements KernelTrick {
private String[] variables = null;
/**
* Возвращает идентификаторы используемых переменных
* @return идентификаторы переменных
*/
public String[] getVariables() {
return this.variables;
}
/**
* Преобразовать двумерный массив данных
* @return преобразованный массив
*/
public double[][] getTransformData(double[][] samples, double[] results) {
this.variables = new String[samples[0].length + 1];
variables[0] = "";
for (int i = 0; i < samples[0].length; i++) {
this.variables[i + 1] = " * x" + i;
}
double result[][] = new double[samples.length][samples[0].length + 1];
for (int i = 0; i < samples.length; i++) {
result[i][0] = 1d;
for (int j = 0; j < samples[0].length; j++) {
result[i][j + 1] = samples[i][j];
}
}
return result;
}
/**
* Преобразовать одномерный массив
* @return одномерный массив
*/
public double[] getTransformData(double[] sample) {
double result[] = new double[sample.length + 1];
for (int i = 0; i < sample.length; i++) {
result[0] = 1d;
for (int j = 0; j < sample.length; j++) {
result[j + 1] = sample[j];
}
}
return result;
}
}
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-63007320863598262482014-12-05T23:28:00.001+05:002014-12-05T23:28:49.226+05:00Ядерные преобразования<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Основное предназначение ядерных преобразований (kernel trick) в нейрокомпьютинге — это расширение количества входных данных искусственного нейрона за счет различных нелинейных функций от комбинаций входных данных.<br />
<a name='more'></a><br />
<br />
Наибольшее распространение ядерные преобразования получили в машине опорных векторов (SVM). Основная причина тому, что SVM также, как и векторная машина Решетова (VMR) – это метод обучения одного единственного искусственного нейрона. Но поскольку машина опорных векторов в отличие от VMR слишком склонна к переобучению и не обладает свойством автопонижения размерности входов, то применение ядер там было чрезмерно осторожным. А точнее, прежде чем задействовать слабый искусственный интеллект машины опорных векторов с ядерными преобразованиями, необходимо было приложить сильный естественный интеллект биологических специалистов. Более того, из-за склонности к переобучению SVM, увеличение размерности входов с помощью ядер приводило к «проклятию размерности», а сами ядерные преобразования для неё были ограниченными, а именно применялись в основном только двухвекторные варианты. Это ограничение было связано с тем, что специалист визуально разглядывал многочисленные двумерные диаграммы с на которых проецировались классы в виде разноцветных точек, с целью обнаружения хоть какой либо сепарабельности с помощью ядер. И только после того, как человек с помощью естественного интеллекта находил подходящее ядро, можно было применить интеллект искусственный.<br />
<br />
С появлением VMR положение дел изменилось. Искусственный интеллект стал сильным, но не по определению Тьюринга, а гораздо сильнее. Ведь по Тьюрингу «сильным» признавался тот искусственный интеллект, который сравнивался с человеческим (неотличим от человеческого). Но VMR уже гораздо сильнее человека. Ведь, если ранее биологическому специалисту по ядерным преобразованиям приходилось выполнять огромную работу с помощью своего естественного интеллекта, чтобы обнаружить какое нибудь подходящее двувекторное или максимум трёхвекторное ядро, то VMR за более короткий промежуток времени может подобрать не одно, а комбинации подходящих многовекторных ядер в более чем трёхмерном пространстве для решения задач бинарной классификации. Естественный интеллект теперь отдыхает. Да впрочем, и пусть отдыхает. Интеллектуальные задачи должны решаться с помощью интеллекта искусственного . Ведь основная задача человечества в том, чтобы освободить самих себя от рутинной деятельности, а не быть рабом обстоятельств. <br />
<br />
Вернёмся к (нашим баранам) ядерным преобразованиям. Поскольку для решения задач нам понадобятся различные ядерные преобразования, то чтобы их унифицировать мы сначала создадим интерфейс с абстрактными необходимыми методами, а потом уже для каждого отдельного преобразования будем создавать соответствующие классы.<br />
<br />
Создаём интерфейс на Java:<br />
<br /></div>
<hr />
<pre>package libvmr;
/**
* Интерфейс ядерных преобразований
* @author Yury V. Reshetov
* @version 1.0
*/
public interface KernelTrick {
/**
* Преобразовать двумерный массив
* @return
*/
public double[][] getTransformData(double[][] samples,double[] results);
/**
* Преобразовать одномерный массив
* @return
*/
public double[] getTransformData(double[] sample);
/**
* Возвращает идентификаторы используемых переменных
* @return идентификаторы переменных
*/
public String[] getVariables();
}
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-25039456579440448042014-12-05T19:16:00.001+05:002014-12-05T19:16:31.751+05:00Нормируем входные данные<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />Нормировка входных данных в нерокомпьютинге применяется давно. Основная её цель — это привести все разнородные (различные единицы измерений) входные сигналы к единому формату. Но если в отдельных случаях для обучения искусственного нейрона можно обойтись и без нормирования, то в случае VMR, этот фокус не пройдёт. Дело в том, что предварительное нормирование входных данных к диапазоно от -1 до 1 включительно является обязательной подготовкой к последующей инвариантности.<br />
<a name='more'></a><br />
Формулы для нормирования в LibVMR линейные, т.к. нелинейность достигается с помощью ядерных преобразований. Сначала для каждой объясняющей переменной находим максимальное (max) и минимальное (min) значения, а потом уже взяв конкретное значение переменной, загоняем его в диапазон от -1 до 1 включительно:<br />
<br />
v' = 2 * (v – min) / (max – min) – 1<br />
<br />
где: <br />
<br />
v' – нормированное значение ненормированной переменной v<br />
<br />
Помимо самого нормирования входных данных нам ещё необходимо отделить значения объясняющих переменных и зависимой переменной, разнеся их по разным массивам.<br />
<br />
Создадим код на Java:</div>
<hr />
<pre>package libvmr;
/**
* Векторная машина Решетова
* @author Yury V. Reshetov
* @version 1.0
*/
public class VMR {
/**
* Максимумы столбцов обучающей выборки
*/
private double[] maxs = null;
/**
* Минимумы столбцов обучающей выборки
*/
private double[] mins = null;
/**
* Значения зависимых переменных
*/
private double[] ideals = null;
/**
* Нормирование обучающей выборки
* @param samples ненормированная обучающая выборка
* @return Нормированная обучающая выборка
*/
private double[][] normSetting(double[][] samples) {
// Вытаскиваем последний столбец обучающей выборки - результаты
this.ideals = new double[samples.length];
for (int i = 0; i < samples.length; i++) {
this.ideals[i] = this.convertToRange(samples[i][samples[0].length - 1], 1d, 0d);
}
double[][] normsamples = new double[samples.length][samples[0].length - 1];
// Ищем максимумы и минимумы
this.maxs = new double[normsamples[0].length];
this.mins = new double[normsamples[0].length];
for (int j = 0; j < normsamples[0].length; j++) {
double max = samples[0][j];
double min = max;
for (int i = 1; i < normsamples.length; i++) {
if (samples[i][j] > max) {
max = samples[i][j];
}
if (samples[i][j] < min) {
min = samples[i][j];
}
}
this.maxs[j] = max;
this.mins[j] = min;
}
// Нормализуем
for (int i = 0; i < normsamples.length; i++) {
for (int j = 0; j < normsamples[0].length; j++) {
normsamples[i][j] = this.convertToRange(samples[i][j],this.maxs[j],this.mins[j]);
}
}
return normsamples;
}
/**
* Преобразование переменных из диапазона от минимального значения до максимального включительно к диапазону от -1 до 1 включительно
* @param value значение переменной
* @param maximmumvalue максимальное значение переменной
* @param minimumvalue минимальное значение переменной
* @return нормированное значение переменной в диапазоне от -1 до 1 включительно
*/
private double convertToRange(double value, double maximmumvalue, double minimumvalue) {
return 2d * (value - minimumvalue) / (maximmumvalue - minimumvalue) - 1d;
}
}
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-60722403716204883412014-12-05T11:34:00.001+05:002014-12-05T23:31:16.437+05:00Создадим сепаратор<div dir="ltr" style="text-align: left;" trbidi="on">
В прошлый раз мы создали парсер, который читает файлы в формате CSV и преобразует их в двумерные массивы данных.<br />
<br />
Но сырые данные для машинного обучения необходимо предварительно разделить на две части:<br />
<br />
<ol style="text-align: left;">
<li>Обучающая выборка, на которой векторная машина - VMR будет создавать математическую модель бинарного классификатора</li>
<li>Тестовая выборка, на которой будет проверяться полученная модель бинарного классификатора для проверки обобщающей способности машинного обучения</li>
</ol>
<br />
<a name='more'></a>Если не выполнить такое разделение, то мы не сможем проверить обобщающую способность. Как уже ранее упоминалось, проблемы при машинном обучении в теории обобщающей способности не могут быть в алгоритме, а только в обучающей выборке. Если результаты проверки на тестовой выборке окажутся неудовлетворительными, то это означает, что в обучающей выборке отсутствуют значимые объясняющие переменные - предикторы.<br />
<br />
Соответственно, нам понадобится сепаратор, который будет делить выборку на две части.<br />
<br />
Принцип работы сепаратора устроен так, чтобы в обучающей выборке представители обоих бинарных классов были представлены одинаково, т.е. количество примеров для обоих классов должно быть равным. Если этого не сделать, то результат обучения будет более надёжным для того класса, который представлен большинством примеров.<br />
<br />
А в тестовой выборке, частоты примеров для обоих классов должны быть близки к частотам этих же классов в генеральной совокупности. В этом случае мы сможем более достоверно вычислить значения чувствительности (SE) и специфичности (SP) и прочие характеристики обобщающей способности обобщённой модели бинарного классификатора, чтобы принять решение о том, пригодна ли модель для прикладного использования или же необходимо провести дополнительные исследования с целью выявления более значимых предикторов.<br />
<br />
Создадим сепаратор на Java: <br />
<br />
<hr />
package libvmr;<br /><br />import java.util.ArrayList;<br />import java.util.Collections;<br /><br />/**<br /> * Сепаратор, разделяющий выборку на обучающую и тестовую части<br /> * @author Yury V. Reshetov<br /> * @version 1.0<br /> */<br />public class Separator {<br /> /**<br /> * Исходная выборка<br /> */<br /> private double[][] samples = null;<br /> /**<br /> * Обучающая выборка<br /> */<br /> private double[][] trainsamples = null;<br /> /**<br /> * Тестовая выборка<br /> */<br /> private double[][] testsamples = null;<br /><br /> /**<br /> * Получить тестовую часть<br /> * @return тестовая часть<br /> */<br /> public double[][] getTestsamples() {<br /> return testsamples;<br /> }<br /><br /> /**<br /> * Получить обучающую часть<br /> * @return обучающая часть<br /> */<br /> public double[][] getTrainsamples() {<br /> return trainsamples;<br /> }<br /><br /> public Separator(double[][] patterns) {<br /> this.samples = patterns;<br /><br /> ArrayList<double[]> trues = new ArrayList<double[]>();<br /> ArrayList<double[]> falses = new ArrayList<double[]>();<br /> for (int i = 0; i < samples.length; i++) {<br /> if (samples[i][samples[i].length - 1] > 0.5) {<br /> trues.add(samples[i]);<br /> } else {<br /> falses.add(samples[i]);<br /> }<br /> }<br /> Collections.shuffle(trues);<br /> Collections.shuffle(falses);<br /><br /> int lenmin = Math.min(trues.size(), falses.size());<br /> int lenmax = Math.max(trues.size(), falses.size());<br /> lenmax = (lenmax - lenmin) / 2 + lenmin;<br /><br /> this.trainsamples = new double[lenmin][samples[0].length];<br /> this.testsamples = new double[lenmax][samples[0].length];<br /> for (int i = 0; i < lenmin; i++) {<br /> if ((i % 2) == 0) {<br /> this.trainsamples[i] = trues.get(i);<br /> this.testsamples[i] = falses.get(i);<br /><br /> } else {<br /> this.trainsamples[i] = falses.get(i);<br /> this.testsamples[i] = trues.get(i);<br /> }<br /> }<br /><br /> if (lenmax != lenmin) {<br /> ArrayList<double[]> r = new ArrayList<double[]>();<br /> if (trues.size() > lenmin) {<br /> r = trues;<br /> } else {<br /> r = falses;<br /> }<br /> for (int i = lenmin; i < lenmax; i++) {<br /> this.testsamples[i] = r.get(i);<br /> }<br /> }<br /> }<br />}<br /></div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-79227351764588809982014-12-05T10:45:00.004+05:002014-12-05T19:28:57.790+05:00Создаём парсер<div dir="ltr" style="text-align: left;" trbidi="on">
Поскольку для алгоритма машинного обучения необходимы данные, то эти
данные нужно откуда-то загружать. Чаще всего для хранения и передачи
данных используется наиболее распространенный формат файлов CSV. Данный
формат был разработан вовсе не для машинного обучения, а для обмена
данными между различными электронными таблицами. Но пригодился и в
искусственном интеллекте, поскольку обучающие выборки также являются
табличными данными. Более того, зачастую информацию, например, в научных
исследованиях, сначала заносят в электронные таблицы, а потом уже с
помощью машинного обучения пытаются найти закономерности.<br />
<a name='more'></a><br />
<br />
Поэтому,
наш парсер также будет брать данные из файлов в формате CSV. В качестве
разделителей табличных ячеек будет использоваться символ точки с
запятой. А в качестве разделителя дробной и целой части числовых данных
будет использоваться либо точка, либо запятая. К тому же первая строка
файла будет содержать наименования входных данных (зависимых
переменных). Вторая строка будет содержать наименования единиц измерений
для данных. Начиная с третьей строки пойдут уже сами данные в
виде чисел. Первый столбец файла будет содержать идентификаторы строк.
Зависимая переменная у нас будет всего одна и не будет иметь
наименований, а соответственно и единиц измерений. Диапазон зависимой
переменной такой же как и для логистической регрессии: 1 - событие
истинно, 0 - событие ложно.<br />
Конечно же, необходимо не только парсить информацию из файлов, но и обрабатывать ошибки. В нашем случае недопустимо, если какие либо числовые данные будут представлены в нечисловом формате. Также недопустимы пропущенные данные, для этого будет применяться проверка на количество ячеек в строках и если будут найдены различия, то должно выдаваться сообщение об ошибке.<br />
<br />
В таком случае, если
например, нам необходимо будет создать файл для машинного обучения
задаче XOR, то содержимое файла, созданное в текстовом редакторе будет
выглядеть так:<br />
<br />
;v0;v1;<br />
;n/a;n/a;<br />
sample0;0;0;0<br />
sample1;0;1;1<br />
sample2;1;0;1<br />
sample3;1;1;0<br />
<br />
Сохраним файл с именем xor.csv<br />
<br />
Теперь его можно открыть в какой нибудь электронной таблице, например, в MS Excel или в Open Office Calc. <br />
<br />
<br />
Но нам нужно обрабатывать выборки не в электронных таблицах, а с помощью нашей библиотеки LibVMR. Дополнительно, наш парсер исключит из таблицы первый столбец - идентификаторы строк, т.к. они не нужны для бинарной классификации, а необходимы для тех, кто заполняет таблицы, чтобы не перепутать источники информации.<br />
<br />
Создадим код парсера на Java:<br />
<br />
<hr />
<pre>package libvmr;
import java.io.*;
import java.util.*;
/**
* Парсинг входного файла из формата CSV
* @author Yury V. Reshetov
* @version 1.0
*/
public class Parser {
/**
* Названия входных признаков
*
*/
private String[] ids = null;
/**
* Единицы измерения для входных признаков
*/
private String[] units = null;
/**
* Сообщение об ошибке
*/
private String error = null;
/**
* Парсинг
* @param file Имя входного файла
* @return Массив обучающей выборки
*/
public double[][] parsing(File file) {
try {
// Загружаем весь текст в ОЗУ
BufferedReader bufferedreader = new BufferedReader(new FileReader(file));
String s = "";
String strings = "";
while ((s = bufferedreader.readLine()) != null) {
if (! s.trim().equals("")) {
strings = strings + s + "\n";
}
}
bufferedreader.close();
//Считаем количество строк и столбцов
StringTokenizer stringtokenizer = new StringTokenizer(strings, "\n");
int i = 0; // Счетчик количества строк
int j = 0; // Счетчик количества столбцов
while (stringtokenizer.hasMoreTokens()) {
String string = stringtokenizer.nextToken().trim();
StringTokenizer stringtokenizer1 = new StringTokenizer(string, ";");
j = 0;
while (stringtokenizer1.hasMoreTokens()) {
stringtokenizer1.nextToken();
j++;
}
i++;
}
int rows = i - 2; // Количество строк в обучающей выборке
int colls = j - 1; // Количество столбцов в обучающей выборке
double[][] samples = new double[rows][colls];
this.ids = new String[colls - 1];
this.units = new String[colls - 1];
// Первые две строки: наименования входных значений и их единицы измерения
stringtokenizer = new StringTokenizer(strings, "\n");
if (i > 2) {
for (int n = 0; n < 2; n++) {
String string = stringtokenizer.nextToken().trim();
StringTokenizer stringtokenizer1 = new StringTokenizer(string, ";");
if (! string.startsWith(";")) {
// Пропускаем первый столбец
if (stringtokenizer1.hasMoreTokens()) {
stringtokenizer1.nextToken();
}
}
j = 0;
while (stringtokenizer1.hasMoreTokens()) {
String data = stringtokenizer1.nextToken();
if (n == 0) {
this.ids[j] = data.trim();
} else {
this.units[j] = data.trim();
}
j++;
}
}
}
// Строки, начиная с третьей
i = 0;
int prev_j = 0; // Количество элементов в предыдущей строке
while (stringtokenizer.hasMoreTokens()) {
String string = stringtokenizer.nextToken().trim();
StringTokenizer stringtokenizer1 = new StringTokenizer(string, ";");
prev_j = j;
j = 0;
// Пропускаем первый столбец
if (! string.startsWith(";")) {
if (stringtokenizer1.hasMoreTokens()) {
stringtokenizer1.nextToken();
}
}
while (stringtokenizer1.hasMoreTokens()) {
String data = stringtokenizer1.nextToken();
// Заменим все разделители-запятые для числовых строк на точки
samples[i][j] = Double.parseDouble(data.replace(',','.'));
j++;
}
if ((i > 0) && (j != prev_j)) {
int current = i + 1;
if (j > prev_j) {
this.error = "Количество элементов в строке " + i + " меньше чем в строке " + current;
}
if ((j < prev_j)) {
this.error = "Количество элементов в строке " + current + " меньше чем в строке " + i;
}
return null;
}
i++;
}
return samples;
} catch (Exception exception) {
this.error = exception.getMessage();
}
return null;
}
/**
* Метод возвращает названия входных параметров
* @return названия входных параметров
*/
public String[] getIDs() {
return this.ids;
}
/**
* Метод возвращает наименования единиц измерения
* @return наименования единиц измерения
*/
public String[] getUnits() {
return this.units;
}
/**
* Метод возвращает сообщение об ошибке
* @return сообщение об ошибке, либо null если ошибки отсутствуют
*/
public String getError() {
return this.error;
}
}
</pre>
<br />
<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-29760764863900518212014-11-19T21:06:00.001+05:002014-12-05T10:38:02.954+05:00Прогнозируем банкротства<div dir="ltr" style="text-align: left;" trbidi="on">
Ещё одна задачка, решённая с помощью LibVMR <br />
<br />
В репозитории uci.edu есть выборка для предсказания банкротств. См. <a href="http://archive.ics.uci.edu/ml/datasets/Qualitative_Bankruptcy">http://archive.ics.uci.edu/ml/datasets/Qualitative_Bankruptcy</a><br />
<br />
Авторы: Myoung-Jong Kim, Ingoo Han опубликовали статью под названием: «The discovery of experts decision rules from qualitative bankruptcy data using genetic algorithms».<br />
<br />
См. <a href="http://koasas.kaist.ac.kr/handle/10203/3685">http://koasas.kaist.ac.kr/handle/10203/3685</a><br />
<br />
Судя по оригинальной авторской статье, выборка предназначалась для генетических алгоритмов, т. к. предполагалось, что для других алгоритмов она не по зубам. <br />
<br />
Однако, вынужден развеять сомнения авторов относительно нейросетевых способностей.<br />
<a name='more'></a><br />
<br />
Саму выборку можно скачать по адресу: <a href="http://archive.ics.uci.edu/ml/machine-learning-databases/00281/">http://archive.ics.uci.edu/ml/machine-learning-databases/00281/</a><br />
<br />
В качестве зависимых переменных используются предсказания экспертов по признакам:<br />
<br />
x0 - Индустриальный риск<br />
x1 - Управление рисками<br />
x2 - Финансовая гибкость<br />
x3 - Кредитоспособность<br />
x4 - Конкурентоспособность<br />
x5 - Операционный риск<br />
<br />
Все значения зависимых переменных категориальны и имеют одно из трёх значений:<br />
<br />
P – положительно<br />
A - средне<br />
N – негативно<br />
<br />
В качестве значений зависимой переменной d применяются категориальные обозначения:<br />
<br />
NB – отсутствие банкротства<br />
B – дефолт<br />
<br />
Я заменил в выборке все категориальные значения числовыми, чтобы скормить их искусственному нейрону с ядром МГУА:<br />
<br />
P на 1<br />
A на 0<br />
N на -1<br />
NB на 0<br />
B на 1<br />
<br />
После этого было проведено несколько этапов случайных разбиений примеров из выборки на обучающую и тестовую части с последующими обучениями алгоритма на обучающей части и валидацией на части тестовой.<br />
<br />
Все этапы на обучающих частях выборки проходили без ошибок. На тестовых частях изредка появлялась всего одна ошибка в виде ложноотрицательного примера.<br />
<br />
Если ошибки не появлялись, то искусственный нейрон генерировал примерно схожие многочлены с незначительными различиями весовых коэффициентов. <br />
<br />
В качестве окончательного решения был взят один из таких многочленов в виде неравенства:<br />
<br />
d = -0.5416484169221631 - x4 - 0.1670687860369955 * x3 - 0.2497157539794443 * x2 + 0.1665362934918911 * x2 * x1 -0.33296421350101096 * x2 * x0 -0.16702978658298784 * x3 * x2 * x1 * x0 > 0<br />
<br />
где: <br />
<br />
Значение d > 0 прогнозирует банкротство. Значение d < 0 говорит об отсутствии предпосылок для дефолта.<br />
<br />
Подстановка многочлена в виде формулы в электронную таблицу, содержащую всю выборку, подтвердила безошибочность неравенства на всех примерах.<br />
<br />
Как видно из неравенства, объясняющая переменная x5, обозначающая операционный риск была признана незначимой для прогноза и исключена из формулы.<br />
<br />
Несмотря на утверждения авторов о том, что информация в выборке содержит субъективные выводы экспертов, а потому якобы могут иметь место потенциальные проблемы, тем не менее, как выяснилось, субъективизм никоим образом не сказался на репрезентативности. Ведь если разделив выборку на две равные части, можно выявить закономерности в любой из частей с минимальной специфичностью в виде одной ложноотрицательной ошибкой в единственном примере и с максимальной безошибочной классификацией.<br />
<br />
P/S: На просторах интернета можно найти разные статьи, ссылающиеся на вышеуказанную выборку, например: <a href="http://www.mecs-press.org/ijisa/ijisa-v6-n1/IJISA-V6-N1-5.pdf">http://www.mecs-press.org/ijisa/ijisa-v6-n1/IJISA-V6-N1-5.pdf</a></div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-6863213679455682652014-11-19T11:01:00.000+05:002014-12-05T10:36:40.730+05:00Пример применения машинного обучения в медицинской диагностике<div dir="ltr" style="text-align: left;" trbidi="on">
Чтобы продемонстрировать возможности высоких технологий в области робастого искусственного интеллекта, попробуем решить с помощью LibVMR задачу из репозитория uci.edu под названием Acute Inflammations. См. <a href="http://archive.ics.uci.edu/ml/datasets/Acute+Inflammations">http://archive.ics.uci.edu/ml/datasets/Acute+Inflammations</a><br />
<a name='more'></a><br />
<br />
Авторы работы J.Czerniak, H.Zarzycki<sup>[1]</sup>
, которая в переводе на русский язык именуется как: “Использование сырых информационных данных для потенциальной диагностики мочевыделительных путей”, выложили в репозиторий файлы, в которых собрана информация по медицинской диагностике, пригодная для решения с помощью бинарных классификаторов. Задача, которую поставили перед собой авторы заключалась в том, чтобы создать из сырых информационных данных экспертную систему для диагностики двух урологических заболеваний: воспаление мочевого пузыря и пиелонефрита (воспалений почечной лоханки). В качестве объясняющих переменных в файле приведены симптомы заболеваний:<br />
<br />
x0 - Температура пациента {35C-42C}<br />
x1 - Тошнота {да, нет}<br />
x2 - Боли в пояснице {да, нет}<br />
x3 - Чрезмерно частое мочеиспускание {да, нет}<br />
x4 - Боли при мочеиспускании {да, нет}<br />
x5 - Жжение мочеиспускательного канала, зуд, отек выходе уретры {да, нет}<br />
<br />
В качестве зависимых переменных указано два диагноза:<br />
<br />
d1 - Воспаление мочевого пузыря {да, нет}<br />
d2 - Пиелонефрит {да, нет}<br />
<br />
Я попытался решить эту же задачу с помощью одного искусственного нейрона, на входы которого подаются комбинации произведений зависимых переменных в виде <a href="http://yury-v-reshetov.blogspot.com/2014/11/blog-post.html" rel="nofollow" target="_blank">МГУА</a>.<br />
<br />
Основная цель:<br />
<br />
<ol style="text-align: left;">
<li>Обучить искусственный нейрон на обучающей выборке с последующим тестированием его на контрольной выборке. Обе части генеральной выборки разделяются случайным образом 50% на 50%.</li>
<li>Выявить незначимые симптомы заболеваний — редукция синапсов искусственного нейрона.</li>
<li>Выявить зависимости в виде многочленов.</li>
</ol>
<br />
Результаты обучения искусственного нейрона:<br />
<br />
Во всех случаях, т. е. для обоих диагнозов чувствительность (SE) и специфичность (SP), как на обучающих выборках, так и на контрольных достигала значения AUC = 100% (безошибочно).<br />
<br />
В обоих случаях (диагнозах) редукции подвергались два симптома: x0 - температура пациента и x4 - боли при мочеиспускании. Т. е. данные симптомы, судя информации в выборке, не являются значимыми (информационными) для постановки диагнозов. Т. е. либо являются дезинформирующими, либо необязательными последствиями осложнений, вызванных основными заболеваниями мочевыделительных путей.<br />
<br />
Приведём оставшиеся после редукции симптомы к диапазону от -1 до 1 включительно:<br />
<br />
x1 - Тошнота {1 - да, -1 - нет}<br />
x2 - Боли в пояснице {1 - да, -1 - нет}<br />
x3 - Чрезмерно частое мочеиспускание {1 - да, -1 - нет}<br />
x5 - Жжение мочеиспускательного канала, зуд, отек выходе уретры {1 - да, -1 - нет}<br />
<br />
В этом случае весовые коэффициенты нейрона для диагностики воспаления мочевого пузыря сходятся к неравенству:<br />
<br />
d1 = 0.9999994285717551 * x3 - x5 * x3 + 0.9999988571435102 * x2 * x1 + 0.9999994285717551 * x3 * x2 * x1 > 0<br />
<br />
где: d1 > 0 – свидетельствует о диагнозе воспаления мочевого пузыря, а d1 < 0 об отсутствии воспаления.<br />
<br />
Упростим неравенство, округлив весовые коэффициенты:<br />
<br />
<div style="text-align: center;">
d1 = x3 * (1 - x5 + x2 * x1) + x2 * x1 > 0</div>
<br />
<br />
Неравенство для пиелонефрита:<br />
<br />
d2 = x2 + 0.9999994285720817 * x3 * x2 + 0.9999971428604082 * x1 - 0.9999988571441633 * x5 * x1 > 0<br />
<br />
где: d2 > 0 – свидетельствует о диагнозе пиелонефрита, а d2 < 0 об отсутствии.<br />
<br />
<br />
Упростим его, округлив весовые коэффициенты:<br />
<br />
<div style="text-align: center;">
d2 = x2 * (1 + x3) + x1 * (1 - x5) > 0</div>
<br />
Задача решена. Желающие могут проверить правильность неравенств, загрузив выборку из репозитория, сконвертировав её в электронные таблицы с последующим вводом формул неравенств и сравнений результатов. См. <a href="http://archive.ics.uci.edu/ml/machine-learning-databases/acute/">http://archive.ics.uci.edu/ml/machine-learning-databases/acute/</a><br />
<br />
Примечание: Что характерно для обоих диагнозов, так это отрицательный знак у зависимой переменной x5. Но данная переменная используется только в качестве уточняющей, т. к. она присутствует в качестве сомножителя с другими зависимыми переменными.<br />
<br />
Однако, я решил проверить ещё одну гипотезу, на предмет наличия зависимостей и симптомов и диагнозов. Если мы хотим поставить диагноз для пиелонефрита, в случае когда нам известен диагноз для воспаления мочевого пузыря d1 (1 – воспаление имеет место, -1 — воспаление не обнаружено), то получаем такое неравенство:<br />
<br />
<div style="text-align: center;">
d2 = x1 * x3 * d1 > 0</div>
<br />
где: d2 > 0 – свидетельствует о диагнозе пиелонефрита, а d2 < 0 об его отсутствии.<br />
<br />
Поскольку зависимая переменная d1 не подверглась редукции, то предполагается наличие зависимости между воспалением мочевого пузыря и пиелонефритом с учётом двух дополнитеьных симптомов: тошноты и чрезмерно частом мочеиспускании. <br />
<br />
Литература:<br />
<br />
1. J.Czerniak, H.Zarzycki, Application of rough sets in the presumptive diagnosis of urinary system diseases, Artifical Inteligence and Security in Computing Systems, ACS'2002 9th International Conference Proceedings, Kluwer Academic Publishers,2003, pp. 41-51
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-5469135528021643042014-11-18T20:05:00.001+05:002014-12-05T10:33:46.013+05:00Три поколения алгоритмов машинного обучения<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div lang="ru-RU" style="margin-bottom: 0cm;">
Искусственный
нейрон впервые был описан психологами
из США Уоренном Мак-Маккалоком и Вальтером
Питсом в статье: McCulloch W.S., Pitts W. A logical
Calculus of Ideas Immanent in Nervous Activity — Bull. Mathematical
Biophysics, 1943</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm; text-align: center;">
<b>Первое поколение
алгоритмов машинного обучения</b></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
Однако, несмотря
на то, что предполагались предпосылки
применения искусственных нейронов для
логических вычислений, каких либо
результатов добиться не удавалось до
до тех пор пока канадский нейрофизиолог
не разработал дельта-правило самообучения
с подкреплением для искусственного
нейрона, опубликованное в статье: Hebb,
D. O. The organization of behavior: a neuropsychological theory. -
John Wiley & Sons, New York, 1949<br />
<a name='more'></a></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
Тем не менее,
прикладное применение нейрокомпьютинга
было отложено ещё на 2 года.
</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
В 1951 г. коннективист
из США Марвин Минский построил
самообучающийся искусственный нейрон
на электронных лампах и приступил к его
исследованию.</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
В 1958 г. психолог
из США Френк Розенблатт доказал теорему,
согласно которой машинное обучение
искусственного нейрона с подкреплением
может привести к решению задачи бинарной
классификации при определённых условиях.
В 1959 г. Ф. Розенблатт приступил к созданию
первой многослойной нейронной сети -
перцептрона. Однако, эта попытка не
оправдала возложенных на неё надежд:
перцептрон несмотря на хорошую обучающую
способность не обладал обобщающей
способностью.
</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
Марвин Минский,
перешёл из лагеря коннективистов в
лагерь противников коннективистского
подхода, сформулировав ряд проблем, без
решения которых задачи бинарной
классификации неразрешимы.</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm; text-align: center;">
<b>Второе поколение
алгоритмов машинного обучения</b></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
В 1974 г. советскими
статистиками Владимиром Вапником и
Алексеем Червоненкисом была разработана
теория распознавания образов. На базе
этой теории, также был разработан
алгоритм машинного обучения (бинарная
классификация), названный машиной
опорных векторов. Вместо многослойной
структуры нейронных сетей, некоторые
входные сигналы подвергаются двухвекторным
ядерным преобразованиям (<span lang="en-US">kernel
trick).</span></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
Суть теории
распознавания образов заключается в
том, что алгоритмы, построенные на поиске
экстремума целевой функции бинарной
классификации (минимизация эмпирического
риска), теряют свойство повышения
обобщающей способности при увеличении
степеней свободы алгоритма машинного
обучения до некоторого предела. При
превышении предела, несмотря на дальнейший
рост обучающей способности алгоритма,
обобщающая способность начинает
умаляться.
</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
Машина опорных
векторов не решала прежних проблем,
указанных М. Минским и не обладала
обобщающей способностью. Но теория
распознавания образов, несмотря на
частично ложные выводы (в частности
вывод об «однозначности» решения
минимизации структурного эмпирического
риска), тем не менее привела в конечном
итоге к созданию свёрточных нейронных
сетей, где за счет ограничений степеней
свободы алгоритмов машинного обучения,
удалось впервые за всю историю
нейрокомпьютинга научиться различать
изображения кошек от других изображений.</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm; text-align: center;">
<b>Третье поколение
алгоритмов машинного обучения</b></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
В 2014 г. дилетант
из бывшего Советского Союза Юрий Решетов,
применил метод машинного обучения,
основанный инвариантности классов
бинарной классификации (приведению
двух классов к одному), на минимаксе
эмпирического риска (Теория антагонистических
игр двух лиц с нулевой суммой) и применения
критерия Шелли (Теория кооперативных
игр), названный <span lang="en-US">VMR (</span>векторная
машина Решетова).
</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
Результат
превзошёл ожидания:</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<ol>
<li><span lang="ru-RU">При
повышении числа степеней свободы с
помощью ядерных преобразований,
обобщающая способность алгоритма
улучшается при наличии хотя бы пары
значимых входных значений. А это
позволяет без предварительных методов
подбирать ядерные преобразования для
входных векторов, ограничиваясь лишь
ёмкостью компьютерных оперативных
запоминающих устройств.</span> </li>
<li>Решена проблема
проклятия размерности, т. к. алгоритм
<span lang="en-US">VMR</span> ещё в процессе обучения
обнуляет весовые коэффициенты для
незначимых входов (автоматическое
понижение размерности) без применения
дополнительных методов, например,
таких, как метод главных компонент </li>
<li>Низкая
обобщающая способность свидетельствует
о том, что проблема находится не в
алгоритме машинного обучения, а в
обучающей выборке (мусор на входах).</li>
<li>Скорость
обучения алгоритма близка к линейной
и пропорциональна сумме количества
входов искусственного нейрона и
количества примеров в обучающей выборке.</li>
</ol>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
Следует заметить,
что авторы теории распознавания образов
были недалеки от решения проблемы
машинного переобучения:</div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<ol>
<li>Машина опорных
векторов содержит одноклассовый
алгоритм, который практически решает
проблему инвариантности.</li>
<li>В рамках
теории была рассмотрена возможность
применения минимакса эмпирического
риска, но очень поверхностно. В результате
чего, авторы пришли к ложному выводу о
потенциальной бесперспективности
поиска решений в этом направлении.</li>
</ol>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
<div lang="ru-RU" style="margin-bottom: 0cm;">
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0tag:blogger.com,1999:blog-8026747702532969376.post-85042260455418871832014-11-18T20:03:00.000+05:002014-12-07T10:52:41.314+05:00ТОСАМО<div dir="ltr" style="text-align: left;" trbidi="on">
Данный блог будет постепенно раскрывать основы "Теории обобщающей
способности алгоритмов машинного обучения" (ТОСАМО). Однако, записи в
блоге будут посвящены не только теории, но и практической части. А
именно теоретическая часть будет сопровождаться и прикладной в виде
реализации с помощью технологии Java в виде библиотеки LibVMR
(библиотека векторной машины Решетова), а также испытаниям на прикладных
примерах (больших и малых данных), взятых из различных репозиториев.<br />
<br />
Основные положения теории обобщающей способности:<br />
<br />
<ol style="text-align: left;">
<li>Алгоритм машинного обучения, обладающий обобщающей способностью, невозможно переобучить. Т.е. проблема переобучения для таких алгоритмов отсутствует, а потому теорией обобщающей способности даже не рассматривается (для переобучающихся алгоритмов есть теория распознавания образов и статистическая теория обучения, разработанные Владимиром Вапником и Алексеем Червоненкисом).</li>
<li>Алгоритм машинного обучения, обладающий обобщающей способностью, можно только недообучить.</li>
<li>Причиной недообучения алгоритмов обладающих обобщающей способностью является непредставительная обучающая выборка.</li>
<li> Обучающая выборка может быть непредставительной из-за того, что в ней недостает необходимого и достаточного для полного обучения: значимых факторов или обучающих примеров или степеней свободы для значимых факторов.</li>
<li>Алгоритмы машинного обучения, обладающие обобщающей способностью, игнорируют избыточные факторы, обучающие примеры и степени свободы для факторов, если обучающая выборка представительна.</li>
</ol>
Векторная машина Решетова (VMR) - это алгоритм машинного обучения для одного искусственного нейрона, как и SVM, но в отличие от машины опорных векторов, обладающий обобщающей способностью.<br />
<br />
Как отличить алгоритм обладающий обобщающей способностью от алгоритма с переобучением? Для этого нужно взять большую представительную выборку и разделить её на две части: обучающую с достаточным для полного обобщения количеством примеров и тестовую. После чего добавить в обе части непредставительные факторы со случайными значениями и избыточные степени свободы, например, с помощью ядерных преобразований. Обучаем алгоритм на первой части выборки. Если алгоритм обладает обобщающей способностью, то его результативность на тестовой части выборки не ухудшится. Если алгоритм склонен к переобучению, то будет заметно значительное ухудшение его обобщающей способности на тестовой части выборки.<br />
<br />
Впрочем, даже если обучающая часть выборки не является полностью
представительной, то увеличение степеней свободы в случае обучения на
ней алгоритма обладающего обобщающей способностью может привести к
увеличению результативности на тестовой части. В случае обучения
переобучающегося алгоритма на обучающей части выборки, даст заметное
ухудшение обобщающей способности на тестовой части.<br />
<br />
Таким образом,
разделив выборку на две части: обучающую и тестовую и обучив на первой
части выборки алгоритм машинного обучения, обладающий обобщающей способностью, можно определить насколько представительна обучающая часть выборки.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/16978448511467616228noreply@blogger.com0