НейроГалактика

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » НейроГалактика » Программная реализация » boxCounting в d-мерном пространстве.


boxCounting в d-мерном пространстве.

Сообщений 1 страница 7 из 7

1

Всем привет.
Это мой первый пост на этом форуме.
Форум показался познавательным, поэтому зарегистрировался.
Программированием в области нейросетей и анализа финансовых временных рядов занимаюсь сравнительно недавно... Пишу на Java.
Теперь ближе к делу...
часто в статьях по нейроанализу финансовых временных рядов можно встретить понятия энтропии, кросс-энтропии, при этом не говорится, как именно надо считать эти величины.
Т.е. сама смысловая нагружка энтропии понятна, алгоритмы и их реалиация не совсем прозрачны, в частности алгоритм box-counting.
Поэтому хочется проговорить вслух этапы алгорима box-counting.
Хочется, чтобы те, у кого есть опыт покритиковали мое понимание этого алгоритма и его реализации.
Поскольку исторические данные по S&P500 легко доступны, их и возьмем в рассмотрение.
(данные можно загрузить отсюда: http://ichart.finance.yahoo.com/table.csv?s=^GSPC&d=4&e=11&f=2008&g=d&a=0&b=3&c=1950&ignore=.csv)

Отредактировано Sophocles (2008-05-11 20:01:54)

0

2

Шаг 1.
а)Получение данных.
b)Формирование массива приращений временного ряда.

Я здесь не буду предлагать реализацию всего цикла получения данных через http протокол с удаленнго ресурса непосредственно в память, поэтому ограничимся загрузкой данных из ранее сохраненного csv файла на диск(если надо будет предложить реализацию загрузки данных не из файла, а через http, то к этому можно будет вернуться).
Итак, для чтения csv потока пользуюсь старым и добрым CSVReader (http://opencsv.sourceforge.net/)

Сам ряд приращений временного ряда получается вот так:

Код:
	public static double[][] getArray()
	{
double[][] retValue = null; 
double[][] inputArray = null; //массив массивов приращений Open,High,Low,Close,Volume
double[] row = null; //одна строчка данных в inputArray 
double d1 = 0.0, d2 = 0.0;

CSVReader reader = null; //компонента для чтения csv файла
List lRows = null; //список прочитанных строк файла
String[] str1 = null; //массив значений колонок одной прочитанной строки из файла
String[] str2 = null; //массив значений колонок одной прочитанной строки из файла

try
{
	//загрузить все строчки файла данных
	reader = new CSVReader(new FileReader("sp500.csv"));
	lRows = reader.readAll();

	//здесь удаляется первая строчка из прочитанного файла, 
	//потому что она не несет в себе никакой информации
	lRows.remove(0); //
	
	//здесь инициализируем массив приращений Open,High,Low,Close,Volume
	inputArray = new double[lRows.size() - 1][];

	//в цикле читаем данные начиная не с 0, а с 1 позиции, 
	//потому что сразу считаем приращения.
	for (int i = 1; i < lRows.size(); i++)
	{
str1 = (String[]) lRows.get(i - 1);
str2 = (String[]) lRows.get(i);

row = new double[cellNum];

// open
d1 = DataUtils.getDoubleParameter(str1[1], 0);
d2 = DataUtils.getDoubleParameter(str2[1], 0);
row[0] = d2 - d1;

// high
d1 = DataUtils.getDoubleParameter(str1[2], 0);
d2 = DataUtils.getDoubleParameter(str2[2], 0);
row[1] = d2 - d1;
// low
d1 = DataUtils.getDoubleParameter(str1[3], 0);
d2 = DataUtils.getDoubleParameter(str2[3], 0);
row[2] = d2 - d1;
// close
d1 = DataUtils.getDoubleParameter(str1[4], 0);
d2 = DataUtils.getDoubleParameter(str2[4], 0);
row[3] = d2 - d1;
// volume
d1 = DataUtils.getDoubleParameter(str1[5], 0);
d2 = DataUtils.getDoubleParameter(str2[5], 0);
row[4] = d2 - d1;

inputArray[i - 1] = row;
	}

	retValue = inputArray;
}
catch (Throwable e)
{
	e.printStackTrace();
}

return retValue;
	}

Поскольку мы имеем дело с пятью параметрами(Open,High,Low,Close,Volume), то количество колонок таблички приращений в inputArray считаем равным 5:

Код:
	public static int cellNum = 5;

Для ленивых:

Код:
	public static double getDoubleParameter(String value, double defaultValue)
	{
double retValue = defaultValue;
try
{
	if (value != null)
retValue = Double.valueOf(value).doubleValue();
	else
retValue = defaultValue;
}
catch (NumberFormatException theException)
{
	retValue = defaultValue;
}

return retValue;
	}

Здесь будем накапливать последовательность реализованных процедур:

Код:
	public static void execute()
	{

try
{
	double[][] inputArray = null;

	//загрузить массив приращений для Open,High,Low,Close,Volume
	inputArray = getArray();

}
catch (Throwable e)
{
	e.printStackTrace();
}

	}

Отредактировано Sophocles (2008-05-11 21:57:22)

0

3

Шаг 2.
а) подсчет минимумов и максимумов рядов приращений для Open,High,Low,Close,Volume
б) нормализация данных в inputArray к [0,1] для каждого ряда приращений.

Подсчет минимумов:

Код:
	public static double[] getMinArray(double[][] inputArray)
	{
double[] row = null;
double[] min = null;

min = new double[cellNum];
for (int i = 0; i < cellNum; i++)
	min[i] = Double.MAX_VALUE;

for (int i = 0; i < inputArray.length; i++)
{
	row = inputArray[i];

	for (int j = 0; j < cellNum; j++)
	{
if (row[j] < min[j])
	min[j] = row[j];
	}
}
return min;
	}

подсчет максимумов:

Код:
	public static double[] getMaxArray(double[][] inputArray)
	{
double[] row = null;
double[] max = null;

max = new double[cellNum];
for (int i = 0; i < cellNum; i++)
	max[i] = Double.MIN_VALUE;

for (int i = 0; i < inputArray.length; i++)
{
	row = inputArray[i];

	for (int j = 0; j < cellNum; j++)
	{
if (row[j] > max[j])
	max[j] = row[j];
	}
}
return max;
	}

Нормализация данных:

Код:
	public static void normalizeArray(double[][] inputArray, double[] min, double[] max)
	{
double[] row = null;

for (int i = 0; i < inputArray.length; i++)
{
	row = inputArray[i];
	for (int j = 0; j < row.length; j++)
	{
row[j] = (row[j] + Math.abs(min[j])) / (Math.abs(min[j]) + max[j]);
	}
}
	}

Продолжаем накапливать последовательность реализованных процедур:

Код:
	public static void execute()
	{

try
{
	double[][] inputArray = null;
	double[] min = null;
	double[] max = null;

	//загрузить массив приращений для Open,High,Low,Close,Volume
	inputArray = getArray();
	//получаем массив минимумов рядов приращений
	min = getMinArray(inputArray);
	//получаем массив максимумов рядов приращений
	max = getMaxArray(inputArray);
	//нормализуем массив приращений
	normalizeArray(inputArray, min, max);


}
catch (Throwable e)
{
	e.printStackTrace();
}

	}

Отредактировано Sophocles (2008-05-11 21:56:18)

0

4

Шаг 3.

Далее...
В литературе можно встретиить предложения рассматривать погружения размерности d во временной ряд длины, скажем n.
Цель простая: на вход нейронной сети подавать целую последовательность исторических значений с целью получить оценку следующего значения из временного ряда.
Т.е. на сколько я понимаю, предлагается из массива нормализованных приращений {x(0), x(1),.....,x(n-1), x(n)} сделать что-то типа матрицы, т.е. массив массивов длины d:
{{x(0),x(1),x(2),....,x(d-2), x(d-1)},
{x(1),x(2),x(3),....,x(d-1), x(d)},
{x(2),x(3),x(4),....,x(d), x(d+1)},
...
{x(n-d+1),..................,x(n-1), x(n)}

Здесь и длее для простоты будем рассматривать ряд нормализованных приращений для входных данных по Close. (для остальных все то же самое)
Итак, процедура d мерного погружения нормализированного ряда приращений реализуется так:

Код:
/**
	 * @param inputArray - исходный массив нормализованных приращений
	 * @param d - размерность погружения
	 * @param index - с какими данными работаем(Open,High,Low,Close,Volume)
	 * заметим, что  при index=0 мы будем работать с данными по Close
*/
	public static double[][] getTimeSeries(double[][] inputArray, int d, int index)
	{
double[][] timeSeries = null;
double[] serie = null;

timeSeries = new double[inputArray.length - d + 1][];

for (int i = d - 1; i < inputArray.length; i++)
{
	serie = new double[d];
	for (int j = 0; j < serie.length; j++)
serie[j] = inputArray[i + j - d + 1][index];
	timeSeries[i - d + 1] = serie;
}

return timeSeries;
	}

Продолжаем накапливать последовательность реализованных процедур:

Код:
	public static void execute()
	{

try
{
	double[][] inputArray = null;
	double[] min = null;
	double[] max = null;
	int boxCount = 0;
	int d = 10;
	double[][] timeSeries = null; //матрица d мерного погружения в нормализованный массив приращения для Close

	//загрузить массив приращений для Open,High,Low,Close,Volume
	inputArray = getArray();
	//получаем массив минимумов рядов приращений
	min = getMinArray(inputArray);
	//получаем массив максимумов рядов приращений
	max = getMaxArray(inputArray);
	//нормализуем массив приращений
	normalizeArray(inputArray, min, max);

	//получение d мерного погружения в нормализованный массив приращения для Close
	timeSeries = getTimeSeries(inputArray, d, 0);

}
catch (Throwable e)
{
	e.printStackTrace();
}

	}

Отредактировано Sophocles (2008-05-11 21:26:00)

0

5

Шаг 4.
Непосредственно подсчитываем box-counting.
Для этого, как я понимаю, нужно d-мерное пространство разбить на квадратики со стороной е и подсчитать сколько квадратиков содержит точек сформированного d мерного погружения.

Код:
	 * @param timeSeries - входные данные d-мерного погружения в нормализованный ряд приращений(в нашем случае для Close)
	 * @param d - размерность погружения
	 * @param e - сторона квадрата разбиения d-мерного пространства на квадратики

	public static int boxCount(double[][] timeSeries, int d, double e)
	{
int bj = 0;
double[] serie = null;
HashMap hmBoxes = null;
String boxKey = null;

hmBoxes = new HashMap();
for (int i = 0; i < timeSeries.length; i++)
{
	serie = timeSeries[i];
	boxKey = "";
	for (int j = 0; j < d; j++)
	{
bj = (int) (serie[j] / e);
boxKey += bj + "|";
	}
	hmBoxes.put(boxKey, boxKey);
}

return hmBoxes.size();
	}

Хочется чуток прокомментировать данную реализацию.
По хорошему перед процедурой подсчета квадратиков, содержащих данные из нашего погружения, нужно перенумировать все квадратики и накапливать список номеров тех квадратиков, которые содержат точки нашего d мерного пространства.
Я нумерацию реализовал несколько иначе: я просто проецирую каждый квадратик на каждую из осей d мерного пространства и ключую квадрат не по его номеру, а по строковой записи: "index(0)|index(1)|...|index(d)", где index(.) - это порядковый номер ячейки, куда попала проекция того или иного квадратика d мерного пространства.
Набор "index(0)|index(1)|...|index(d)" однозначно определяет сам квадрат в пространстве, поэтому существенно пользуюсь таким набором и при определении факта нахождения в отдельном квадратике данных нашего d мерного пространства просто записываю идентификатор квадарата "index(0)|index(1)|...|index(d)" в обычный HashMap.
В результате в HashMap-e останется набор уникальных ключей и количество квадратов равно длине HashMap-a.
(если тут еще раз надо что-то пояснить, то могу постраться дать доп. объяснения, но я и так вроде предельно детально описал саму процедуру)

Продолжаем накапливать последовательность реализованных процедур:

Код:
	public static void execute()
	{

try
{
	double[][] inputArray = null;
	double[] min = null;
	double[] max = null;
	int boxCount = 0;
	int d = 10;
	double[][] timeSeries = null; //матрица d мерного погружения в нормализованный массив приращения для Close

	//загрузить массив приращений для Open,High,Low,Close,Volume
	inputArray = getArray();
	//получаем массив минимумов рядов приращений
	min = getMinArray(inputArray);
	//получаем массив максимумов рядов приращений
	max = getMaxArray(inputArray);
	//нормализуем массив приращений
	normalizeArray(inputArray, min, max);

	//получение d мерного погружения в нормализованный массив приращения для Close
	timeSeries = getTimeSeries(inputArray, d, 0);

	//подсчет boxCount для d мерного погружения в нормализованный массив приращения для Close
	//сторона квадрата e берется равной 0.02 (e=0.02)
	boxCount = boxCount(timeSeries, d, 0.02);
	System.out.println("d=" + d+ " boxCount=" + boxCount);

}
catch (Throwable e)
{
	e.printStackTrace();
}

	}

Отредактировано Sophocles (2008-05-11 21:48:11)

0

6

Для чего я это все тут написал.
Просто есть вопросы и некие сомнения по правильности понимания теории и есть сомнения, собственно, по самой реализации.

Вопросы:
1. Правильно ли я понимаю, что такое d-мерное погружение во временной ряд?
2. Правильно ли я понимаю и реализовываю алгоритм boxCounting для d-мерного пространства?

Если что-то неправильно, то прошу прокомментировать - исправим вместе. В результате получим публично доступный алгоритм вычисления boxCounting для d-мерного пространства.

0

7

Привет, Sophocles!
Огромное тебе спасибо за то, что написал такие содержательные посты. Вероятнее всего, ты разочаруешься в этом форуме, потому что тут теперь есть только я... да и то. Пишу я в основном "пустые" посты... лишь бы форум не удалили. Слишком много в свое время было потрачено времени на это, так что было бы жаль, если бы труд нескольких человек просто удалили из-за того, что тут никого нет.

Начиналось все с того, что Вадим (beholder22) написал мне письмо... Нейросетевик, собственно, у нас - именно ОН. Я и с математикой-то ... почти не дружу.

Поэтому даю тебе его контакты:
286-104-869 - аська
8 (485-36) 6-72-90 - телефон (из аськиной инфы).
Можно попробовать еще и личное сообщение ему написать (... но его последний пост на этом форуме... был уже не менее года назад, а, скорее - более).

Я могу просто поболтать с тобой о делах наших скорбных.
Прости, но не то, что помочь, но даже и понять... что ты написал, я не смогу.

0


Вы здесь » НейроГалактика » Программная реализация » boxCounting в d-мерном пространстве.