Методика разработки программного продукта для поиска причин в изменениях трендов в данных
Создание системы предобработки данных; разработка системы классификации на базе методов и алгоритмов машинного обучения, их реализация в программной системе. Предобработка информации, инструкция пользователя, система классификации, машинный эксперимент.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 31.01.2015 |
Размер файла | 917,1 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
3.2.1 Рабочий режим
Данный режим предназначен для обучения классификаторов на основе информации о прошлых событиях и изменениях. Обученные классификаторы применяются для анализа предложенных изменений, после чего система делает предположение о причине данных изменений.
После запуска программы вызывается функция main(), которая записывает дату и время запуска программы, после чего определяет в каком режиме должна работать система - тестовом или рабочем. Для рабочего режима вызывается функция workMode, которой передается информация о файлах с данными для обучения и для выполнения предсказаний, информация о выбранном классификаторе, а также информация о папке в которую надо записать результаты предсказаний.
Функция workMode загружает данные для обучения и данные ля выполнения предсказаний из файлов и трансформирует их в формат Pandas.DataFrame, который удобен для обработки данных, которые можно представить в виде таблицы. Затем система формирует 3 набора данных:
1. X_train - информация о событиях из тренировочных данных
2. y_train - информация о изменениях в трендах в тренировочных данных
3. X_test - информация о изменениях в трендах, объяснение которым должна найти система
После формирования данных наборов, набор y_train (информация о произошедших изменениях в тренировочных данных) проходит через трансформацию с помощью функции preprocessing. MultiLabelBinarizer().
Данная трансформация преобразовывает матрицу текстовых меток (информацию об изменениях в трендах - страну выпуска ценной бумаги, тип изменения в тренде, биржу, на которой торгуется бумага) в формат бинарной матрицы, содержащей метки о присутствии или отсутствии определенного класса в примере. Данное преобразование необходимо, так как использованные в дальнейшем алгоритмы ожидают именно такой формат на вход для выполнения предсказаний.
После этого система тренирует классификатор на базе выбранного алгоритма классификации.
Для этого система сначала выполняет преобразование исходного набора пар текстовых меток о событиях и произошедших одновременно с ними изменениях (напомним, информация о произошедших изменениях уже была преобразована функцией MultiLabelBinarizer) в формат бинарных разряженных матриц, содержащих количество появления каждой из меток с помощью функции CountVectorizer().
Полученные матрицы передается функции TfidfTransformer(). Данная функция выполняет TF-IDF преобразование над переданными матрицами, которое было разобрано ранее. Преобразование выполняется для того, чтобы повысить вес редких параметров событий и понизить вес часто встречающихся характеристик. Например, если подавляющее большинство событий в наборе данных связано с российскими ценными бумагами то событие связанное с ценными бумагами другой страны будет иметь больший вес при обучении классификатора.
Полученные матрицы, содержащие информацию о изменениях и о произошедших одновременно с ними событиях, после преобразования TF-IDF передаются метаклассификатору OneVsRestClassifier(). Данный метаклассификатор использует переданные ему матрицы для выполнения задачи многоклассовой\многотемной классификации с помощью выбранного нами классификатора и стратегии One-vs-all.
Для облегчения задачи последовательного вызова функций CountVectorizer(), TfidfTransformer() и передачи результатов метаклассификатору OneVsRestClassifier() мы воспользуемся так называемым конвейером - Pipeline(). Конвейер просто последовательно применяет переданные ему функции и передает их результат выбранному классификатору.
После обучения классификатора на тестовых данных (команда fit()) мы выполняем предсказание для данных в X_test, то есть пытаемся объяснить изменения в трендах, хранимые в данной переменной. Полученные предсказания проходят обратное преобразование из формата бинарной матрицы, содержащей метки о присутствии или отсутствии определенного класса в примере в формат обычной текстовой информации с помощью функции inverse_transform(). Полученные предсказания сохраняются в текстовый файл. Пример результата:
0,"NegSpike,AAB,Apple Inc,EQTY,REIT,USD,Asian,JPN,XTKS,Internet Software & Services","(American, Bought Back, EQTY, FOX, Movies & Entertainment, Standard, Twenty-First Century Fox Inc, USA, USD, XNGS)"
1. 0 - порядковый номер результата
2. Следом идем набор меток изменения, которое мы пытаемся объяснить, разделенные запятыми.
3. Далее в скобках перечисляются характеристики события, которое предположительно вызвало данное изменение.
По результатам системы производится файл с предсказаниями выполненными с помощью выбранного алгоритма классификации.
3.2.2 Тестовый режим
В тестовом режиме оценивается производительность системы на переданном ей файле с данными с помощью выбранного классификатора. Для оценки производительности системы и качества ее предсказаний попробуем оценивать метрику Precision (доля правильно предсказанных меток от общего количества предсказанных меток). Ожидается, что система будет способна выделить наиболее вероятные причины изменения в трендах цены и сможет предсказать, какие события, скорее всего, происходили одновременно с происходящими изменениями в трендах, то есть сможет указать максимальное количество меток таких корпоративных событий.
В тестовом режиме системе передается файл с тестовыми парами событий и изменений в трендах, после чего данный файл разделяется на два случайных подмножества - тренировочный набор данных (90% исходных пар событий и трендов) и тестовый набор данных (10% исходных пар). После чего выбранный классификатор тренируется на тренировочном наборе данных (процесс полностью аналогичен таковому в рабочем режиме). Затем обученный классификатор запускается для каждого описания изменения тренда в тестовом наборе данных, и система делает предсказания о причинах изменения этого тренда. После этого подсчитывается, сколько из меток предсказанного описания события присутствуют в реально существовавшей паре событие - изменение в тренде. Путем деления полученного количества на общее количество предсказанных меток получаем Precision системы.
По результатам работы системы получаем файл Results.csv, который содержит следующую информацию:
1. Порядковый номер тестового примера
2. Описание тренда, для которого выполнялись предсказания в виде набора меток, разделенных запятыми
3. Какое событие на самом деле происходило одновременно с данным изменением в трендах, заключенное в квадратные скобки.
4. Какой набор меток был предсказан системой, заключенный в скобки.
Пример одной такой записи:
0, PosSpike, ICPT, Intercept Pharmaceuticals Inc, EQTY, REIT, USD, American, USA, XNGS, Biotechnology, [Merger, Standard, ETE, Energy Transfer Equity LP, UNIT, EUNT, USD, American, USA, XNYS, Oil & Gas Storage & Transportation], (American, EQTY, Standard, USA, USD)
3.2.3 Инструкция пользователя
Тестовый режим
Необходимо скопировать файл с программой FactGeneralizer.py в любую папку на пользовательском компьютере. Также необходимо скопировать нужные для работы файлы в любую папку на пользовательском компьютере. В случае работы программы в тестовом режиме необходим один файл с парами событие - изменение в тренде. Далее необходимо открыть командную строку и с помощью команды cd перейти в папку, в которой хранится файл FactGeneralizer.py. Для запуска программы в тестовом режиме необходимо ввести в командной строке следующую команду и нажать Enter:
python FactGeneralizer.py “test” “PriceFacts.csv” “Results.csv” “linear”
Значение параметров приведено ниже:
1) “test” - метка, обозначающая что программа будет работать в тестовом режиме
2) “PriceFacts.csv” - имя файла, содержащего исходные данные
3) “Results.csv” - имя файла, в котором будут сохранены результаты работы программы
4) “linear” - алгоритм классификации, который будет использован программой. Поддерживаются следующие алгоритмы:
1. linear - Машина опорных векторов с линейным ядром и обучением пакетным методом
2. linearWithSGD - Машина опорных векторов с линейным ядром и обучением по методу стохастического градиентного спуска
3. rbf - Машина опорных векторов с Радиальной базисной функцией в качестве ядра, обучение пакетным методом
4. poly - Машина опорных векторов с Полиномиальным ядром, обучение пакетным методом
5. sigmoid - Машина опорных векторов с Сигмоидной функцией в качестве ядра, обучение пакетным методом
6. bayes - Наивный байесовский классификатор
После завершения программы в командной строке будет выведена информация о времени работы программы и информация о precision (точности) программы на тестовых данных. Также в файл результатов будут сохранены тестовые примеры и сделанные системой предсказания.
Ниже приведен пример запуска и получения результатов программы в тестовом режиме.
Рис. 8. Работа системы классификации в тестовом режиме
Рабочий режим
Необходимо скопировать файл с программой FactGeneralizer.py в любую папку на пользовательском компьютере. Также необходимо скопировать нужные для работы файлы в любую папку на пользовательском компьютере. В случае работы программы в рабочем режиме необходимы два файла. Первый из них, содержащий пары «событие - изменение в тренде» будет использован для обучения классификатора. Второй должен содержать записи об изменениях в трендах, которые система попытается объяснить. Далее необходимо открыть командную строку и с помощью команды cd перейти в папку, в которой хранится файл FactGeneralizer.py. Для запуска программы в тестовом режиме необходимо ввести в командной строке следующую команду и нажать Enter:
python FactGeneralizer.py “work” “PriceFacts.csv” “ToPredict.csv”
“Results.csv” “linear”
Значение параметров приведено ниже:
1) “test” - метка, обозначающая что программа будет работать в тестовом режиме
2) “PriceFacts.csv” - имя файла, содержащего исходные данные для тренировки классификатора
3) “ToPredict.csv” - имя файла, содержащего записи об изменениях в тренде, которые система попытается объяснить
4) “Results.csv” - имя файла, в котором будут сохранены результаты работы программы
5) “linear” - алгоритм классификации, который будет использован программой. Поддерживаются следующие алгоритмы:
1. linear - Машина опорных векторов с линейным ядром и обучением пакетным методом
2. linearWithSGD - Машина опорных векторов с линейным ядром и обучением по методу стохастического градиентного спуска
3. rbf - Машина опорных векторов с Радиальной базисной функцией в качестве ядра, обучение пакетным методом
4. poly - Машина опорных векторов с Полиномиальным ядром, обучение пакетным методом
5. sigmoid - Машина опорных векторов с Сигмоидной функцией в качестве ядра, обучение пакетным методом
6. bayes - Наивный байесовский классификатор
После завершения программы в командной строке будет выведена информация о времени работы программы. В файл результатов будет записана информация о каждом изменении в тренде, которое система пыталась объяснить, и описание вероятной причины в данном изменении в тренде. Ниже приведен пример запуска программы в рабочем режиме.
Рис. 9. Работа системы классификации в рабочем режиме
Выводы
Реализована система, осуществляющая предобработку исходных данных о ценах на ценные бумаги и корпоративных событиях, связанных с ценными бумагами. Предобработка создает файл, содержащий информацию о том, какие корпоративные события происходили одновременно с какими изменениями в трендах цен. Далее данная информация передается системе классификации, которая производит преобразование по алгоритму TF-IDF и тренирует классификатор на базе одного из поддерживаемых алгоритмов. В ходе тренировки классификатор определяет, какие параметры корпоративных событий сопутствуют конкретным параметрам в изменениях трендов. Например, классификатор способен обнаружить, что в большинстве случаев одновременно со сломом тренда для ценных бумаг, торгующихся на московской бирже и выпущенных металлургическими компаниями, обычно происходит корпоративное событие связанное с китайскими автопроизводителями.
Обученный классификатор используется далее для поиска причин слома тренда цен переданных классификатору ценных бумаг.
4. Машинный эксперимент
В ходе машинного эксперимента этап предобработки информации был запущен на следующем наборе тестовых данных:
1. 8542 ценных бумаги.
2. 1576688 записей о ценах на эти ценные бумаги, данные записи содержат информацию о ценах за год.
3. 53154 записи о корпоративных событиях, связанных с этими ценными бумагами.
Были установлены следующие параметры работы для предобработчика данных:
1. changeThreshold = 0.3. При изменении цены на эту величину за день считаем, что возможен слом тренда.
2. spikeThreshold = 6. При изменении цены на эту величину за день считаем, что произошел всплеск в цене.
3. dateThreshold = 3. При предположении о том, что произошел слом тренда, система сравнит последнюю цену с ценой через 3 дня чтобы проверить гипотезу о сломе тренда.
Системе предобработки данных понадобилось около 19 часов работы для завершения предобработки исходных данных. По результатам было получено 26975 пар событие - изменение в тренде. Полученные пары были использованы для работы системы классификации в тестовом режиме.
Система была запущена три раза для каждого из поддерживаемых классификаторов. Тренировка классификаторов производилась на случайно выбранных 90% данных (24280) и далее тестировалась на 2695 оставшихся записях.
Ниже представлена таблица с результатами тестирования:
Таблица 1
Результаты тестирования различных классификаторов
Тип классификатора |
Всего предсказано меток |
Корректно предсказано меток |
Precision, % |
Время выполнения программы, сек. |
|
SVM с линейным ядром, SGD обучение |
15047 |
12119 |
81 |
21 |
|
15217 |
12424 |
82 |
23 |
||
14977 |
12121 |
81 |
19 |
||
SVM с линейным ядром, обучение пакетным градиентным спуском |
15157 |
12192 |
80 |
159 |
|
15286 |
12471 |
82 |
146 |
||
15218 |
12200 |
80 |
147 |
||
SVM с ядром RBF |
1765880 |
28073 |
1.59 |
9985 |
|
1765880 |
28083 |
1.59 |
9950 |
||
1765880 |
28050 |
1.59 |
9949 |
||
SVM с полиномиальным ядром |
1765880 |
28128 |
1.59 |
8620 |
|
1765880 |
28118 |
1.59 |
9639 |
||
1765880 |
28081 |
1.59 |
9960 |
||
SVM с ядром - сигмоид |
1765880 |
28093 |
1.59 |
9685 |
|
1765880 |
28112 |
1.59 |
8739 |
||
1765880 |
28084 |
1.59 |
8677 |
||
Наивный Байесовский классификатор |
17904 |
12627 |
70.53 |
12 |
|
18141 |
12672 |
69.85 |
12 |
||
16790 |
12812 |
76 |
12 |
Выводы
Как и предполагалось ранее, машина опорных векторов с нелинейным ядром (RBF, полиномиальное ядро или сигмоид) не подходит для решения данной задачи. Каждый из этих трех классификаторов сильно переучивается на тестовых данных и дает практически одинаковые прогнозы для всех тестовых примеров. Данные классификаторы требуют значительное время для обучения (порядка 3 часов каждый) и демонстрируют одинаковую точность, равную примерно 1,5%.
Как и предполагалось ранее, наилучшую точность демонстрирует машина опорных векторов с линейным ядром. При этом обучение по методу стохастического градиентного спуска дает резкий прирост в скорости обучения - средняя время тренировки по методу стохастического градиентного спуска равно 20 секундам, против 150 секунд при обучении по методу пакетного градиентного спуска. При этом переход на стохастический градиентный спуск не снижает точности классификатора - она все также близка к 80%.
Наивный Байесовский классификатор также хорошо показал себя в машинном эксперименте. Его отличительной чертой можно назвать большую агрессивность при выполнении предсказаний (если машина опорных векторов в среднем предсказывала около 15000 меток то Наивный Байесовский Классификатор предсказывал около 17500 меток). Также можно отметить больший разброс точности данного классификатора - если результаты SVM отличаются друг от друга примерно на 1% то результаты NBC колеблются в более широких пределах и могут отличаться друг от друга почти на 7%. Тем не менее, данный алгоритм обучается гораздо быстрее, чем SVM, даже при ее обучении по методу стохастического градиентного спуска. NBC в среднем потребовалось 12 секунд на тренировку, в то время как SVM в среднем обучалась около 20 секунд. Также следует отметить, что NBC до лучше масштабируется до больших объемов данных, соответственно с ростом объема обучающих данных время, необходимое на его обучение, будет расти медленнее, чем для SVM.
Таким образом, применение классификаторов NBC и SVM действительно позволяет достичь поставленной нами задачи. Данные классификаторы способны с большой точностью (примерно 70-80%) предсказывать, какими характеристиками обладают события, которые должны одновременно происходить с переданными им записями о сломах в трендах цен.
Заключение
В рамках данной работы нам удалось решить задачу по поиску наиболее вероятных причин в изменениях в трендах данных. Задача, которая стояла перед нами является гибридом multi-label и multiclass классификации. Для каждого примера нам требуется предсказывать одну или несколько меток (например, страна, в которой произошло событие, или индустрия, с которой связано произошедшее событие), каждой метке может быть присвоено несколько различных значений. Подобные задачи имеют название multi-task классификация или multiclass - multi-output классификация. Задачи, подобные этой относительно успешно решаются в такой области как Document classification (классификация документов), что позволило нам использовать методы, традиционно применяемые в рамках классификации документов
Задача состояла из двух частей:
1) Извлечение из информации о ценах данные о том для каких ценных бумаг когда наблюдалось изменение в тренде в цене (если цена на бумагу росла некоторое время, то в какой момент она начала снижаться или стала неизменной).
2) Разработка системы, которая сможет обучиться на информации о предшествующих событиях и изменениях в трендах выявляя наиболее вероятные характеристики событий - причин, и далее сумеет предсказать, какими характеристиками наиболее вероятно обладает событие, которое вызвало переданный системе слом в тренде.
Первая часть задачи была решена с помощью языка программирования C#.
Вторая задача была решена с помощью языка python и открытой библиотеки программного обеспечения для машинного обучения scikit-learn. Данная библиотека имеет открытый исходный код, предлагает эффективную реализацию всех популярных алгоритмов машинного обучения и поддерживается большим сообществом разработчиков и исследователей из университетов и лабораторий всего мира. При решении второй части задачи мы использовали алгоритм TF-IDF который позволил нам повысить весомость редких событий и снизить вес частых событий. Далее были применены алгоритмы классификации Машина Опорных Векторов и Наивный Байесовский Классификатор. Проверена эффективность различных ядер для Машины Опорных Векторов, а также эффективность пакетного градиентного спуска и стохастического градиентного спуска. Установлено, что наилучшей точностью обладают SVM с линейным ядром и Наивный Байесовский Классификатор. Нам удалось получить точность классификации около 80%. Также установлено, что обучение по методу стохастического градиентного спуска позволяет значительно ускорить тренировку SVM классификатора без каких-либо жертв в точности.
Реализованная система обладает приемлемой производительностью. И достаточной точностью для ее практического применения. Архитектура разработанной программы позволяет включить её в состав более сложной системы.
Список использованных ресурсов
1. Scikit-learn: Machine Learning in Python, Pedregosa et al., JMLR 12, 2011, pp. 2825-2830.
2. C# 5.0 in a Nutshell 5th Edition, Albahari J., Albahari B., 2012, pp.319 - 423.
3. Нейронные сети. Полный курс, Хайкин С., Издательский дом "Вильямс", 2006, с. 417 - 458
4. Python manual [Электронный ресурс]
5. Причинно-следственный анализ [Электронный ресурс]
6. Инвестиции - Учебник, Уильям Ф. Шарп, Инфра-М, 2001
Приложение 1
Система предобработки информации
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace FactEventAnalyzer
{
public struct Parameters
{
public double ChangeThreshold;
public int SecIdFrom;
public int SecIdTo;
public int DateFrom;
public int DateTo;
public double SpikeThreshold;
public Logger fileLogger;
public int minerDateThreshold;
public string folderForMLFiles;
}
class Program
{
static void Main()
{
DateTime startDate = System.DateTime.Now;
Parameters curParam =
readInitialParams(AppDomain.CurrentDomain.BaseDirectory);
curParam.fileLogger.writeToLog("Fact-Event analysis tool started");
FactMiner.runFactMiner(CurParam: curParam);
curParam.fileLogger.writeToLog("Fact-Event analysis tool completed, it
took " + (System.DateTime.Now - startDate).TotalSeconds.ToString() + "
seconds.");
}
static Parameters readInitialParams(string paramPass)
{
Parameters curParam = new Parameters();
XElement config = XElement.Load(paramPass + "\\Config.xml");
XElement LogConfig = config.Element("logging").Element("logFolder");
curParam.fileLogger = new
Logger(LogConfig.Attribute("path").Value.ToString());
XElement factMinerSettings = config.Element("factMinerSettings");
curParam.ChangeThreshold = (double)
factMinerSettings.Element("changeThreshold").Attribute("value");
curParam.SecIdFrom =
(int)factMinerSettings.Element("securities").Attribute("from");
curParam.SecIdTo =
(int)factMinerSettings.Element("securities").Attribute("to");
curParam.DateFrom =
(int)factMinerSettings.Element("dates").Attribute("from");
curParam.DateTo = (int)factMinerSettings.Element("dates").Attribute("to");
curParam.SpikeThreshold =
(double)factMinerSettings.Element("spikeThreshold").Attribute("value");
curParam.minerDateThreshold =
(int)factMinerSettings.Element("dateThreshold").Attribute("value");
curParam.folderForMLFiles =
(string)factMinerSettings.Element("filesForMl").Attribute("value");
string copyConfigFile = paramPass+"\\Log\\Config" +
curParam.fileLogger.composeDateString(mode: 0) + ".xml";
System.IO.File.Copy(paramPass + "\\Config.xml", copyConfigFile);
curParam.fileLogger.writeToLog("Config loaded, copy of loaded config
file:\n " + copyConfigFile);
return curParam;
}
}
}
FactMiner.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace FactEventAnalyzer
{
static class FactMiner
{
enum ChangeType
{
Growing = 0,
Decreasing = 1,
Unchanged = 2,
PosSpike = 3,
NegSpike = 4
}
enum FieldType
{
Ask = 0,
Bid = 1,
Price = 2
}
public static void runFactMiner(Parameters CurParam)
{
DateTime startDate = DateTime.Now;
CurParam.fileLogger.writeToLog("Mining of Facts started");
FactEventAnalysisDBDataContext dbContext = new
FactEventAnalysisDBDataContext();
dbContext.usp_clearFactsTables(dateFrom: CurParam.DateFrom, dateTo:
CurParam.DateTo, secIdFrom: CurParam.SecIdFrom, secIdTo:
CurParam.SecIdTo, isPrices: true, isCorax: false, isSpike: true);
CurParam.fileLogger.writeToLog("Price Facts and Spike Facts are cleared,
it took " + (DateTime.Now - startDate).TotalSeconds);
var SecurityQuery = from security in dbContext.SecuritiesSources
orderby security.SecId
where security.SecId >= CurParam.SecIdFrom && security.SecId <=
CurParam.SecIdTo && dbContext.PricesSources.Any(p => (p.SecId ==
security.SecId && p.DateTick >= CurParam.DateFrom && p.DateTick <=
CurParam.DateTo))
select security;
int totalSecs = SecurityQuery.Count();
int curSecNum = 0;
foreach (FactEventAnalyzer.SecuritiesSource curSec in SecurityQuery)
{
curSecNum++;
CurParam.fileLogger.writeToLog(curSecNum.ToString() + "/" +
totalSecs.ToString() + ", SecId is " + curSec.SecId);
analyzePriceField(DbContext: dbContext, CurSec: curSec, curParam:
CurParam);
CurParam.fileLogger.writeToLog("Price completed");
analyzeAskField(DbContext: dbContext, CurSec: curSec, curParam:
CurParam);
CurParam.fileLogger.writeToLog("Ask completed");
analyzeBidField(DbContext: dbContext, CurSec: curSec, curParam:
CurParam);
CurParam.fileLogger.writeToLog("Bid completed");
if (CurParam.SpikeThreshold > 0)
{
produceSpikeFacts(DbContext: dbContext, CurSec: curSec, curParam:
CurParam);
CurParam.fileLogger.writeToLog("Spikes analyzed");
}
}
CurParam.fileLogger.writeToLog("Price Facts are produced.\n Start time: "
+ startDate.ToString() +
"\n Finish time: " + System.DateTime.Now.ToString() +
"\n Securities processed: " + totalSecs.ToString() +
"\n Total runtime: " + (System.DateTime.Now -
startDate).TotalSeconds.ToString());
CurParam.fileLogger.writeToLog("Starting Corax Facts production");
produceCoraxFacts(curParam: CurParam);
CurParam.fileLogger.writeToLog("Corax Facts are produced.Starting to
save results to file.\n");
var hypothesisQuery = from hypothesis in dbContext.PriceFactsHypothesis
select hypothesis;
string resultsFile = CurParam.folderForMLFiles + "\\PriceFacts_" +
CurParam.fileLogger.composeDateString(mode: 0) + ".csv";
string delimiter = ",";
Type type = typeof(PriceFactsHypothesi);
PropertyInfo[] properties = type.GetProperties();
string line = "";
foreach (PropertyInfo property in properties)
{
line += property.Name + delimiter;
}
System.IO.StreamWriter file = new System.IO.StreamWriter(resultsFile,
true);
file.WriteLine(line);
file.Close();
foreach (var hypothesis in hypothesisQuery)
{
properties = type.GetProperties();
line = "";
foreach (PropertyInfo property in properties)
{
string value = property.GetValue(hypothesis) != null
? property.GetValue(hypothesis).ToString()
: string.Empty; // or whatever you want the default text to be
line += value + delimiter;
}
file = new System.IO.StreamWriter(resultsFile, true);
file.WriteLine(line);
file.Close();
}
var hypothesisQuery2 = from hypothesis in
dbContext.SpikeFactsHypothesis
select hypothesis;
resultsFile = CurParam.folderForMLFiles + "\\SpikeFacts_" +
CurParam.fileLogger.composeDateString(mode: 0) + ".csv";
type = typeof(SpikeFactsHypothesi);
properties = type.GetProperties();
line = "";
foreach (PropertyInfo property in properties)
{
line += property.Name + delimiter;
}
file = new System.IO.StreamWriter(resultsFile, true);
file.WriteLine(line);
file.Close();
foreach (var hypothesis in hypothesisQuery2)
{
properties = type.GetProperties();
line = "";
foreach (PropertyInfo property in properties)
{
string value = property.GetValue(hypothesis) != null
? property.GetValue(hypothesis).ToString()
: string.Empty; // or whatever you want the default text to be
line += value + delimiter;
}
file = new System.IO.StreamWriter(resultsFile, true);
file.WriteLine(line);
file.Close();
}
CurParam.fileLogger.writeToLog("Fact mining have completed.\n Start
time: " + startDate.ToString() +
"\n Finish time: " + System.DateTime.Now.ToString() +
"\n Total runtime of Fact Miner: " + (System.DateTime.Now -
startDate).TotalSeconds.ToString());
}
static void analyzePriceField(FactEventAnalysisDBDataContext DbContext,
FactEventAnalyzer.SecuritiesSource CurSec, Parameters curParam)
{
var PriceQuery = from price in DbContext.PricesSources
where price.SecId.Equals(CurSec.SecId) && price.DateTick >=
curParam.DateFrom && price.DateTick <= curParam.DateTo
orderby price.DateTick
select price;
bool isFirst = true;
var previousPrice = new FactEventAnalyzer.PricesSource();
var startPrice = new FactEventAnalyzer.PricesSource();
var lastPrice = new FactEventAnalyzer.PricesSource();
bool isSkip = false;
bool isSecond = false;
int skipNum = 0;
ChangeType curChange = ChangeType.Unchanged;
foreach (FactEventAnalyzer.PricesSource curPrice in PriceQuery)
{
lastPrice = curPrice;
if (isFirst == true)
{
startPrice = curPrice;
isFirst = false;
isSecond = true;
}
else
{
if (isSecond == true)
{
curChange = determineChangeType(prevPrice: startPrice.Price, curPrice:
curPrice.Price, changeThreshold: curParam.ChangeThreshold);
previousPrice = curPrice;
isSecond = false;
}
else
{
if (isSkip == false)
{
if (determineChangeType(prevPrice: previousPrice.Price, curPrice:
curPrice.Price, changeThreshold: curParam.ChangeThreshold) !=
curChange)
{
isSkip = true;
}
else
{
previousPrice = curPrice;
}
}
else
{
if (skipNum < (curParam.minerDateThreshold - 1))
{
skipNum++;
}
else
{
skipNum = 0;
isSkip = false;
if (determineChangeType(prevPrice: previousPrice.Price, curPrice:
curPrice.Price, changeThreshold: curParam.ChangeThreshold) !=
curChange)
{
insertNewPriceFact(curChange, dateStart: startPrice.DateTick, dateEnd:
previousPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Price);
curChange = determineChangeType(prevPrice: previousPrice.Price,
curPrice: curPrice.Price, changeThreshold: curParam.ChangeThreshold);
startPrice = previousPrice;
previousPrice = curPrice;
}
else
{
previousPrice = curPrice;
}
}
}
}
}
}
if (isSkip == true)
{
insertNewPriceFact(changeType: curChange, dateStart: startPrice.DateTick,
dateEnd: previousPrice.DateTick, secId: CurSec.SecId, fieldType:
FieldType.Price);
insertNewPriceFact(changeType:
determineChangeType(previousPrice.Price, curPrice: lastPrice.Price,
changeThreshold: curParam.ChangeThreshold), dateStart:
previousPrice.DateTick, dateEnd: lastPrice.DateTick, secId: CurSec.SecId,
fieldType: FieldType.Price);
}
else
{
if (isFirst != true)
{
insertNewPriceFact(changeType: curChange, dateStart: startPrice.DateTick,
dateEnd: lastPrice.DateTick, secId: CurSec.SecId, fieldType:
FieldType.Price);
}
}
}
static void analyzeAskField(FactEventAnalysisDBDataContext DbContext,
FactEventAnalyzer.SecuritiesSource CurSec, Parameters curParam)
{
var PriceQuery = from price in DbContext.PricesSources
where price.SecId.Equals(CurSec.SecId) && price.DateTick >=
curParam.DateFrom && price.DateTick <= curParam.DateTo
orderby price.DateTick
select price;
bool isFirst = true;
var previousPrice = new FactEventAnalyzer.PricesSource();
var startPrice = new FactEventAnalyzer.PricesSource();
var lastPrice = new FactEventAnalyzer.PricesSource();
bool isSkip = false;
bool isSecond = false;
int skipNum = 0;
ChangeType curChange = ChangeType.Unchanged;
foreach (FactEventAnalyzer.PricesSource curPrice in PriceQuery)
{
lastPrice = curPrice;
if (isFirst == true)
{
startPrice = curPrice;
isFirst = false;
isSecond = true;
}
else
{
if (isSecond == true)
{
curChange = determineChangeType(prevPrice: startPrice.AskPrice,
curPrice: curPrice.AskPrice, changeThreshold: curParam.ChangeThreshold);
previousPrice = curPrice;
isSecond = false;
}
else
{
if (isSkip == false)
{
if (determineChangeType(prevPrice: previousPrice.AskPrice, curPrice:
curPrice.AskPrice, changeThreshold: curParam.ChangeThreshold) != curChange)
{
isSkip = true;
}
else
{
previousPrice = curPrice;
}
}
else
{
if (skipNum < (curParam.minerDateThreshold - 1))
{
skipNum++;
}
else
{
skipNum = 0;
isSkip = false;
if (determineChangeType(prevPrice: previousPrice.AskPrice, curPrice:
curPrice.AskPrice, changeThreshold: curParam.ChangeThreshold) !=
curChange)
{
insertNewPriceFact(curChange, dateStart: startPrice.DateTick, dateEnd:
previousPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Ask);
curChange = determineChangeType(prevPrice: previousPrice.AskPrice,
curPrice: curPrice.AskPrice, changeThreshold: curParam.ChangeThreshold);
startPrice = previousPrice;
previousPrice = curPrice;
}
else
{
previousPrice = curPrice;
}
}
}
}
}
}
if (isSkip == true)
{
insertNewPriceFact(changeType: curChange, dateStart: startPrice.DateTick,
dateEnd: previousPrice.DateTick, secId: CurSec.SecId, fieldType:
FieldType.Ask);
insertNewPriceFact(changeType:
determineChangeType(previousPrice.AskPrice, curPrice: lastPrice.AskPrice,
changeThreshold: curParam.ChangeThreshold), dateStart:
previousPrice.DateTick, dateEnd: lastPrice.DateTick, secId: CurSec.SecId,
fieldType: FieldType.Ask);
}
else
{
if (isFirst != true)
{
insertNewPriceFact(changeType: curChange, dateStart: startPrice.DateTick,
dateEnd: lastPrice.DateTick, secId: CurSec.SecId, fieldType:
FieldType.Ask);
}
}
}
static void analyzeBidField(FactEventAnalysisDBDataContext DbContext,
FactEventAnalyzer.SecuritiesSource CurSec, Parameters curParam)
{
var PriceQuery = from price in DbContext.PricesSources
where price.SecId.Equals(CurSec.SecId) && price.DateTick >=
curParam.DateFrom && price.DateTick <= curParam.DateTo
orderby price.DateTick
select price;
bool isFirst = true;
var previousPrice = new FactEventAnalyzer.PricesSource();
var startPrice = new FactEventAnalyzer.PricesSource();
var lastPrice = new FactEventAnalyzer.PricesSource();
bool isSkip = false;
bool isSecond = false;
int skipNum = 1;
ChangeType curChange = ChangeType.Unchanged;
foreach (FactEventAnalyzer.PricesSource curPrice in PriceQuery)
{
lastPrice = curPrice;
if (isFirst == true)
{
startPrice = curPrice;
isFirst = false;
isSecond = true;
}
else
{
if (isSecond == true)
{
curChange = determineChangeType(prevPrice: startPrice.BidPrice, curPrice:
curPrice.BidPrice, changeThreshold: curParam.ChangeThreshold);
previousPrice = curPrice;
isSecond = false;
}
else
{
if (isSkip == false)
{
if (determineChangeType(prevPrice: previousPrice.BidPrice, curPrice:
curPrice.BidPrice, changeThreshold: curParam.ChangeThreshold) !=
curChange)
{
isSkip = true;
}
else
{
previousPrice = curPrice;
}
}
else
{
if (skipNum < (curParam.minerDateThreshold - 1))
{
skipNum++;
}
else
{
skipNum = 1;
isSkip = false;
if (determineChangeType(prevPrice: previousPrice.BidPrice, curPrice:
curPrice.BidPrice, changeThreshold: curParam.ChangeThreshold) !=
curChange)
{
insertNewPriceFact(curChange, dateStart: startPrice.DateTick, dateEnd:
previousPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Bid);
startPrice = previousPrice;
previousPrice = curPrice;
curChange = determineChangeType(prevPrice: startPrice.BidPrice, curPrice:
previousPrice.BidPrice, changeThreshold: curParam.ChangeThreshold);
}
else
{
previousPrice = curPrice;
}
}
}
}
}
}
if (isSkip == true)
{
insertNewPriceFact(changeType: curChange, dateStart: startPrice.DateTick,
dateEnd: previousPrice.DateTick, secId: CurSec.SecId, fieldType:
FieldType.Bid);
insertNewPriceFact(changeType:
determineChangeType(previousPrice.BidPrice, curPrice: lastPrice.BidPrice,
changeThreshold: curParam.ChangeThreshold), dateStart:
previousPrice.DateTick, dateEnd: lastPrice.DateTick, secId: CurSec.SecId,
fieldType: FieldType.Bid);
}
else
{
if (isFirst != true)
{
insertNewPriceFact(changeType: curChange, dateStart: startPrice.DateTick,
dateEnd: lastPrice.DateTick, secId: CurSec.SecId, fieldType:
FieldType.Bid);
}
}
}
static void insertNewPriceFact(ChangeType changeType, int dateStart, int
dateEnd, int secId, FieldType fieldType)
{
FactEventAnalysisDBDataContext dbContext = new
FactEventAnalysisDBDataContext();
FactEventAnalyzer.PriceFactsTable newFact = new
FactEventAnalyzer.PriceFactsTable();
newFact.ChangeType = changeType.ToString();
newFact.DateStart = dateStart;
newFact.DateEnd = dateEnd;
newFact.SecID = secId;
newFact.FieldType = fieldType.ToString();
dbContext.PriceFactsTables.InsertOnSubmit(newFact);
dbContext.SubmitChanges();
}
static void insertNewSpikeFact(ChangeType changeType, int date, int secId,
FieldType fieldType)
{
FactEventAnalysisDBDataContext dbContext = new
FactEventAnalysisDBDataContext();
FactEventAnalyzer.SpikeFactsTable newSpikeFact = new
FactEventAnalyzer.SpikeFactsTable();
newSpikeFact.Date = date;
newSpikeFact.FieldType = fieldType.ToString();
newSpikeFact.SecId = secId;
newSpikeFact.SpikeType = changeType.ToString();
dbContext.SpikeFactsTables.InsertOnSubmit(newSpikeFact);
dbContext.SubmitChanges();
}
static void produceCoraxFacts(Parameters curParam)
{
int? insertedSecs = 0, insertedCoraxes = 0;
DateTime startDate = DateTime.Now;
FactEventAnalysisDBDataContext dbContext = new
FactEventAnalysisDBDataContext();
dbContext.usp_clearFactsTables(dateFrom: curParam.DateFrom, dateTo:
curParam.DateTo, secIdFrom: curParam.SecIdFrom, secIdTo:
curParam.SecIdTo, isPrices: false, isCorax: true, isSpike: false);
curParam.fileLogger.writeToLog("Corax Facts are cleared, it took " +
(DateTime.Now - startDate).TotalSeconds);
dbContext.usp_populateCoraxFactsTable(curParam.DateFrom,
curParam.DateTo, curParam.SecIdFrom, curParam.SecIdTo, ref
insertedSecs, ref insertedCoraxes);
curParam.fileLogger.writeToLog("Corax Facts are produced.\n Start time: "
+ startDate.ToString() +
"\n Finish time: " + System.DateTime.Now.ToString() +
"\n Securities processed: " + insertedSecs.ToString() +
"\n Facts inserted: " + insertedCoraxes.ToString() +
"\n Total runtime: " + (System.DateTime.Now -
startDate).TotalSeconds.ToString());
}
static void produceSpikeFacts(FactEventAnalysisDBDataContext
DbContext, FactEventAnalyzer.SecuritiesSource CurSec, Parameters
curParam)
{
var PriceQuery = from price in DbContext.PricesSources
where price.SecId.Equals(CurSec.SecId) && price.DateTick >=
curParam.DateFrom && price.DateTick <= curParam.DateTo
orderby price.DateTick
select price;
bool isFirst = true;
FactEventAnalyzer.PricesSource prevPrice = new
FactEventAnalyzer.PricesSource();
foreach (FactEventAnalyzer.PricesSource curPrice in PriceQuery)
{
if (isFirst == true)
{
prevPrice = curPrice;
isFirst = false;
}
else
{
double changeAmount = (double)(100 * (curPrice.Price - prevPrice.Price) /
prevPrice.Price);
if (Math.Abs(changeAmount) > curParam.SpikeThreshold)
{
if (changeAmount < 0)
{
insertNewSpikeFact(changeType: ChangeType.NegSpike, date:
curPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Price);
}
else
{
insertNewSpikeFact(changeType: ChangeType.PosSpike, date:
curPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Price);
}
}
changeAmount = (double)(100 * (curPrice.AskPrice - prevPrice.AskPrice) /
prevPrice.AskPrice);
if (Math.Abs(changeAmount) > curParam.SpikeThreshold)
{
if (changeAmount < 0)
{
insertNewSpikeFact(changeType: ChangeType.NegSpike, date:
curPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Ask);
}
else
{
insertNewSpikeFact(changeType: ChangeType.PosSpike, date:
curPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Ask);
}
}
changeAmount = (double)(100 * (curPrice.BidPrice - prevPrice.BidPrice) /
prevPrice.BidPrice);
if (Math.Abs(changeAmount) > curParam.SpikeThreshold)
{
if (changeAmount < 0)
{
insertNewSpikeFact(changeType: ChangeType.NegSpike, date:
curPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Bid);
}
else
{
insertNewSpikeFact(changeType: ChangeType.PosSpike, date:
curPrice.DateTick, secId: CurSec.SecId, fieldType: FieldType.Bid);
}
}
prevPrice = curPrice;
}
}
}
static ChangeType determineChangeType(decimal prevPrice, decimal
curPrice, double changeThreshold)
{
double changeAmount = (double)(100 * (curPrice - prevPrice) / prevPrice);
if (Math.Abs(changeAmount) < changeThreshold)
{
return ChangeType.Unchanged;
}
else
{
if (changeAmount < 0)
{
return ChangeType.Decreasing;
}
else
{
return ChangeType.Growing;
}
}
}
}
}
Logger.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FactEventAnalyzer
{
public class Logger
{
private Logger() { }
string logFile;
public Logger(string logFolder)
{
this.logFile = logFolder + "\\FactMiner_" + composeDateString(mode: 0) +
".log";
}
public string composeDateString(int mode=1)
{
DateTime tempDate = System.DateTime.Now;
if (mode == 0)
{
return (tempDate.Year.ToString() + tempDate.Month.ToString("D2") +
tempDate.Day.ToString("D2")
+ "T" + tempDate.Hour.ToString("D2") + tempDate.Minute.ToString("D2")
+ tempDate.Second.ToString("D2")
+ "_" + tempDate.Millisecond.ToString("D3"));
}
else
{
return (tempDate.Year.ToString() + "." + tempDate.Month.ToString("D2") +
"." + tempDate.Day.ToString("D2")
+ "T" + tempDate.Hour.ToString("D2") + ":" +
tempDate.Minute.ToString("D2") + ":" + tempDate.Second.ToString("D2")
+ "." + tempDate.Millisecond.ToString("D3"));
}
}
public void writeToLog(string logMessage)
{
System.IO.StreamWriter file = new System.IO.StreamWriter(this.logFile,
true);
file.WriteLine(composeDateString() + " " + logMessage);
file.Close();
}
}
}
Приложение 2. Файл конфигурации системы предобработки информации
<factEventAnalyzer>
<logging>
<logFolder path="D:\DiplomaProject\AnalyzingWorkFolder\log"/>
</logging>
<factMinerSettings>
<changeThreshold value="0.3"/>
<securities from="0" to="99999999"/>
<dates from="0" to="99999"/>
<spikeThreshold value="6"/>
<dateThreshold value = "3"/>
<filesForMl value="D:\DiplomaProject\FilesForML"/>
</factMinerSettings>
</factEventAnalyzer>
Приложение 3. Хранимые процедуры и табличные представления базы данных FactEventAnalysisDB
usp_populateCoraxFactsTable
USE [FactEventAnalysisDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[usp_populateCoraxFactsTable]
@DateFrom int = 0,
@DateTo int = 999999999,
@SecIdFrom int = 0,
@SecIdTo int = 999999999,
@SecuritiesInserted int = 0 output,
@CoraxesInserted int = 0 output
AS
BEGIN
create table #Inserted
(
UniqueCoraxId int not null,
SecId int not null
)
insert into dbo.CoraxFactsTable
(
SecId,
UniqueCoraxId,
EffectiveDate,
ReportedDate,
EventType,
EventMajorType
)
output
inserted.UniqueCoraxId,
inserted.SecId
into #Inserted
SELECT
c.SecId as SecId,
c.UniqueCoraxId as UniqueCoraxid,
CAST(c.EffectiveDate as int) as EffectiveDate,
CAST(c.ReportedDate as int) as ReportedDate,
c.EventType as EventType,
c.EventMajorType as EventMajorType
from
dbo.CoraxesSource as c
where
c.SecId >= @SecIdFrom
and c.SecId <= @SecIdTo
and (
(c.ReportedDate>=@DateFrom
and c.ReportedDate<=@DateTo)
or
(c.EffectiveDate>=@DateFrom
and c.EffectiveDate<=@DateTo)
)
select @CoraxesInserted = COUNT(*)
from
#Inserted
select
@SecuritiesInserted = COUNT(t.SecId)
from
(select distinct SecId from #Inserted) as t
END
GO
usp_clearFactsTables
USE [FactEventAnalysisDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[usp_clearFactsTables]
@DateFrom int = 0,
@DateTo int = 999999999,
@SecIdFrom int = 0,
@SecIdTo int = 999999999,
@IsPrices bit = 0,
@IsCorax bit = 0,
@IsSpike bit = 0
AS
BEGIN
IF (@IsPrices = 1)
BEGIN
delete from
dbo.PriceFactsTable
where
SecId >= @SecIdFrom
and SecId <= @SecIdTo
and (
(DateStart >= @DateFrom
and DateStart <=@DateTo)
or
(DateEnd <= @DateTo
and DateEnd >= @DateFrom))
END
IF (@IsSpike = 1)
BEGIN
delete from
dbo.SpikeFactsTable
where
SecId >= @SecIdFrom
and SecId <= @SecIdTo
and [Date] >= @DateFrom
and [Date] <= @DateTo
END
IF (@IsCorax = 1)
BEGIN
delete from
dbo.CoraxFactsTable
where
SecId >= @SecIdFrom
and SecId <= @SecIdTo
and (
(ReportedDate>=@DateFrom
and ReportedDate<=@DateTo)
or
(EffectiveDate>=@DateFrom
and EffectiveDate<=@DateTo))
END
END
GO
SpikeFactsHypothesis
USE [FactEventAnalysisDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE view [dbo].[SpikeFactsHypothesis] as
SELECT
cf.EventType as [CoraxEventType]
,cf.EventMajorType as [CoraxEventMajorType]
,csec.Ticker as [CoraxTicker]
,csec.Issuer as [CoraxIssuer]
,csec.SecType as [CoraxSecType]
,csec.InvType as [CoraxInvType]
,csec.PriceCurrency as [CoraxPriceCurrency]
,csec.Region as[CoraxRegion]
,csec.IssuerCountry as [CoraxIssuerCountry]
,csec.Exchange as [CoraxExchange]
,csec.IndustrySector as [CoraxIndustrySector]
,sf.SpikeType as [ChangeType]
,ssec.Ticker as [ChangeTicker]
,ssec.Issuer as [ChangeIssuer]
,ssec.SecType as [ChangeSecType]
,ssec.InvType as [ChangeInvType]
,ssec.PriceCurrency as [ChangePriceCurrency]
,ssec.Region as [ChangeRegion]
,ssec.IssuerCountry as [ChangeIssuerCountry]
,ssec.Exchange as [ChangeExchange]
,ssec.IndustrySector as [ChangeIndustrySector]
FROM
dbo.CoraxFactsTable as cf
join dbo.SecuritiesSource as csec on cf.SecId = csec.SecId
join dbo.Spikefactstable as sf on cf.EffectiveDate = sf.[Date]
join dbo.SecuritiesSource as ssec on sf.SecId = ssec.SecId
where
sf.FieldType = 'Price'
GO
PriceFactsHypothesis
USE [FactEventAnalysisDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE view [dbo].[PriceFactsHypothesis] as
SELECT
cf.EventType as [CoraxEventType]
,cf.EventMajorType as [CoraxEventMajorType]
,csec.Ticker as [CoraxTicker]
,csec.Issuer as [CoraxIssuer]
,csec.SecType as [CoraxSecType]
,csec.InvType as [CoraxInvType]
,csec.PriceCurrency as [CoraxPriceCurrency]
,csec.Region as[CoraxRegion]
,csec.IssuerCountry as [CoraxIssuerCountry]
,csec.Exchange as [CoraxExchange]
,csec.IndustrySector as [CoraxIndustrySector]
,sf.ChangeType as [ChangeType]
,ssec.Ticker as [ChangeTicker]
,ssec.Issuer as [ChangeIssuer]
,ssec.SecType as [ChangeSecType]
,ssec.InvType as [ChangeInvType]
,ssec.PriceCurrency as [ChangePriceCurrency]
,ssec.Region as [ChangeRegion]
,ssec.IssuerCountry as [ChangeIssuerCountry]
,ssec.Exchange as [ChangeExchange]
,ssec.IndustrySector as [ChangeIndustrySector]
FROM
dbo.CoraxFactsTable as cf
join dbo.SecuritiesSource as csec on cf.SecId = csec.SecId
join dbo.PriceFactstable as sf on cf.EffectiveDate = sf.[DateStart]
join dbo.SecuritiesSource as ssec on sf.SecId = ssec.SecId
where
sf.FieldType = 'Price'
GO
Приложение 4
Система классификации
from __future__ import division
import sys
import csv as csv
import numpy as np
import pandas as pd
from pandas import DataFrame
import sklearn
from sklearn.preprocessing import LabelEncoder
from sklearn.cross_validation import train_test_split
from sklearn.grid_search import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.svm import SVC
from sklearn.svm import LinearSVC
from sklearn import cross_validation, svm, tree
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.neighbors import KNeighborsClassifier
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.multiclass import OneVsRestClassifier
from sklearn import preprocessing
from sklearn.linear_model import SGDClassifier
import random
import warnings
from datetime import datetime
from sklearn.grid_search import GridSearchCV
warnings.filterwarnings("ignore")
selClassifiers = {
'linear': LinearSVC(),
'linearWithSGD': SGDClassifier(),
'rbf': SVC(kernel='rbf', probability=True),
'poly': SVC(kernel='poly', probability=True),
'sigmoid': SVC(kernel='sigmoid', probability=True),
'bayes': MultinomialNB()
}
classifierDescriptions = {
'linearWithSGD': 'linear SVM with SGD training',
'linear': 'linear SVM without SGD training',
'rbf': 'SVM with RBF kernel',
'poly': 'SVM with polynomial kernel',
'sigmoid': 'SVM with sigmoid kernel',
'bayes': 'Naive Bayes classifier'
}
def replacer(text):
return str(str(text).replace("u'",'').replace("'", ''))
def workMode(fileIn, toPredict, fileOut, classif):
work = pd.read_csv(fileIn, header = 0, encoding='utf-8-sig')
work_test = pd.read_csv(toPredict, header = 0, encoding='utf-8-sig')
X_train = []
y_train = []
X_test = []
for i in work[[i for i in list(work.columns.values) if
i.startswith('Change')]].values:
X_train.append(','.join(i.T.tolist()))
X_train = np.array(X_train)
for i in work[[i for i in list(work.columns.values) if
i.startswith('Corax')]].values:
y_train.append(list(i))
for i in work_test[[i for i in list(work_test.columns.values) if
i.startswith('Change')]].values:
X_test.append(','.join(i.T.tolist()))
X_test = np.array(X_test)
lb = preprocessing.MultiLabelBinarizer()
Y = lb.fit_transform(y_train)
print ("Getting results of classifier")
classifier = Pipeline([('vectorizer', CountVectorizer()),('tfidf',
TfidfTransformer()),('clf', OneVsRestClassifier(selClassifiers[classif]))])
classifier.fit(X_train, Y)
predicted = classifier.predict(X_test)
all_labels = lb.inverse_transform(predicted)
df = DataFrame.from_items([('Change', X_test), ('Prediction',all_labels)])
df.Prediction = df.Prediction.map(replacer)
df.to_csv(fileOut)
def testMode(fileIn, fileOut, classif):
df = pd.read_csv(fileIn, header = 0, encoding='utf-8-sig')
rows = random.sample(list(df.index), int(len(df) * 0.9))
work = df.ix[rows]
work_test = df.drop(rows)
X_train = []
y_train = []
X_test = []
y_test = []
for i in work[[i for i in list(work.columns.values) if
i.startswith('Change')]].values:
X_train.append(','.join(i.T.tolist()))
X_train = np.array(X_train)
for i in work[[i for i in list(work.columns.values) if
i.startswith('Corax')]].values:
y_train.append(list(i))
for i in work_test[[i for i in list(work_test.columns.values) if
i.startswith('Change')]].values:
X_test.append(','.join(i.T.tolist()))
X_test = np.array(X_test)
for i in work_test[[i for i in list(work_test.columns.values) if
i.startswith('Corax')]].values:
y_test.append(list(i))
lb = preprocessing.MultiLabelBinarizer()
Y = lb.fit_transform(y_train)
print ("Getting results of %s" % classifierDescriptions[classif])
classifier = Pipeline([('vectorizer', CountVectorizer()),('tfidf',
TfidfTransformer()),('clf', OneVsRestClassifier(selClassifiers[classif]))])
classifier.fit(X_train, Y)
predicted = classifier.predict(X_test)
all_labels = lb.inverse_transform(predicted)
df = DataFrame.from_items([('Test', X_test), ('RealAnswer', y_test),
('Prediction',all_labels)])
CorPred = 0
Total = 0
for classifying, item, labels in zip(X_test, y_test, all_labels):
for res in labels:
if res in item:
CorPred+=1
Total+=len(labels)
print('Predicted correctly %s labels out of %s labels' % (CorPred, Total))
print('Precision is %.2f %%' % (100*float(CorPred)/float(Total)))
df.Prediction = df.Prediction.map(replacer)
df.RealAnswer = df.RealAnswer.map(replacer)
df.to_csv(fileOut)
def main():
start = datetime.now()
print("Program started at %s" % start)
if sys.argv[1] == 'test':
testMode(sys.argv[2], sys.argv[3], sys.argv[4])
elif sys.argv[1] == 'work':
workMode(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])
else:
print('Unknown mode, only test or work modes are available')
end = datetime.now()
print("Program finished at %s" % end)
print("It took %s seconds for program to complete" % (end -
start).total_seconds())
if __name__ == '__main__':
main()
Размещено на Allbest.ru
Подобные документы
Создание сайта-каталога программного обеспечения с поиском на основе булевой модели. Достоинства и недостатки булевой модели. Алгоритм поиска по слову в базе данных системы. Разработка руководства пользователя и администратора по работе с системой.
курсовая работа [1,0 M], добавлен 28.04.2014Обоснование необходимости создания программного продукта. Данные, которые хранятся в базе данных. Обоснование их достаточности. Операции по обработке данных. Описание интерфейса пользователя с иллюстрациями диалоговых окон. Инструкция для пользователя.
курсовая работа [886,5 K], добавлен 11.10.2008Роль классификации документов в решении задач информационного поиска. Методы автоматической классификации документов и этапы построения классифицирующей системы: индексация документа, построение классификаторов на базе обучающих данных, оценка их работы.
курсовая работа [354,2 K], добавлен 13.01.2013Программное обеспечение для получения исходных данных для обучения нейронных сетей и классификации товаров с их помощью. Алгоритм метода обратного распространения ошибки. Методика классификации товаров: составление алгоритма, программная реализация.
дипломная работа [2,2 M], добавлен 07.06.2012Деятельность отдела информационных технологий. Сопровождение аппаратных средств, баз данных и локальной вычислительной сети. Обслуживание телекоммуникаций и защита информации. Разработка программного средства, работающего с базой данных Oracle.
курсовая работа [405,1 K], добавлен 16.09.2012Описание разрабатываемой программы с точки зрения пользователя и программиста. Поэтапная разработка программной системы. Создание базы данных в Access. Разработка структуры классов. Создание структуры для хранения данных. Проектирование интерфейса.
курсовая работа [1,4 M], добавлен 07.08.2013Методы реализации алгоритмов сортировки и алгоритмов поиска на языках программирования высокого уровня. Программирование алгоритмов сортировки и поиска в рамках создаваемого программного средства на языке Delphi. Создание руководства пользователя.
курсовая работа [1,7 M], добавлен 16.04.2012Изучение принципа работы интернет-аукциона (на примере сайта molotok.ru). Способ получения информации с веб-ресурсов. Разработка программного обеспечения с целью создания исходных данных для обучения нейронных сетей и классификации товаров с их помощью.
дипломная работа [2,0 M], добавлен 29.06.2012Сведения о языке Delphi. Основы разработки баз данных. Разработка конвертера таблицы Excel, интерфейса главной формы, модуля отображения, системы поиска информации, средств редактирования. Системные требования программы. Инструкция по эксплуатации.
курсовая работа [2,6 M], добавлен 29.12.2008Особенности алгоритмов, критерии качества. Создание и применение программного продукта на языке Delphi. Тип операционной системы. Внутренняя структура программного продукта. Руководство пользователя и программиста, расчет себестоимости и цены программы.
дипломная работа [1,5 M], добавлен 12.06.2009