![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Фильтрация массива чисел от шума
abun © (2009-08-10 16:10:00)Есть упорядоченный массив чисел типа real. Нужно отфильтровать явно "левые" числа (т.е. видно, что они совсем другой величины). Длина массива не более 1000.
Пример массива:
90,100,2100,2120,2130,2135,2140,2160,2200,2300,2500,3500,4000,100000.
Результатом работы фильтра должно исключение из списка чисел 90, 100 и 100000. "Неправильных" чисел не может быть в массиве много. Точное количество их не указать. Но если очень принципиально, то пусть будет ограничение: не более 4-х.
Казалось бы, задача элементарная. Опробовал: входит ли в интервал
[матожидание*0,8..матожидание*1,2] (0,8 и 1,2 - т.е. -20 и +20% иначе говоря) - не помогает, т.к. матожидание серьезно искажается этими "неправильными" числами и выпадают правильные.
Пробовал и через среднее по разнице между соседними элементами.
Тогда 2 и более соседних "неправильных" чисел прикрывают друг дружку.
Такое ощущение, что задача вообще нерешаема строгим алгоритмом.
Jeer (2009-08-11 18:05:00) [1]Если существует корреляция между курсами ЦБ или иного "уважаемого" источника (а она должна быть, в общем-то), то можно делать отсев по корреляционным зависимостям.
abun (2009-08-11 17:33:00) [2]
> Что-то мне "подсказывает", что после того как автор ветки
> "отфильтрует" (по его терминологии) свой упорядоченный массив,
> он займется прогнозированием этого курса валют на последующий
> период времени:)Пожелаем ему успеха:)
Чушь! Мне это не нужно! Читайте, пожалуйста, сообщение №24. По-моему, там наглядно написано, что будет и для чего. Смысл мне в прогнозировании курсов? Для этого есть форекс и иже с ними.
Smile (2009-08-11 16:10:00) [3]Что-то мне "подсказывает", что после того как автор ветки "отфильтрует" (по его терминологии) свой упорядоченный массив, он займется прогнозированием этого курса валют на последующий период времени
:)
Пожелаем ему успеха
:)
abun (2009-08-11 16:00:00) [4]Согласен, случай неординарный и описать его функцией не представляется возможным. Но все же считаю, что можно найти алгоритм, который бы, например, в 95% принимал решение правильно и отфильтровывал бы "выпадающие" из общего правила числа.
palva (2009-08-11 14:15:00) [5]В статистическом алгоритме всегда будут случаи, когда он работает неправильно. Если у вас есть какие-то предположения о вероятностном распределении входных данных, о характере шума и т. д., тогда можно будет говорить о вероятности того, что алгоритм работает неправильно, подобрать алгоритм наилучший с этой точки зрения. А при существующей постановке задачи к любому алгоритму можно подобрать контрпример, и в то же время невозможно оценить, какой алгоритм лучше.
Павел Калугин (2009-08-11 14:08:00) [6]А может просто импортировать значения из проверненного источника и не городить огород?
abun (2009-08-11 11:44:00) [7]ну так вот этот алгоритм и будет проверять на правильность.
Anatoly Podgoretsky (2009-08-11 11:19:00) [8]> abun (11.08.2009 10:30:26) [26]
А сделать так, что бы в массиве изначально были только правильные данные?
abun (2009-08-11 10:30:00) [9]Единственное, что приходит в голову - считать дисперсию после каждого прохода и если она меньше определенного порога - выйти из цикла. Но как найти этот порог - опять вопрос.
abun (2009-08-11 10:18:00) [10]
> Дмитрий Белькевич (11.08.09 00:47) [21]
> > Но если на конце будет два "левых" числа - фильтр не работает.
> > :(Два раза последовательно проходить не пробовал?
Ну да, получается, конечно. Но как узнать, когда остановить проходы? Фишка этого фильтра в том, что у него на каждом проходе что-то отфильтровывается. Я написал:
var
i:integer;
t,b,a:areal;
d: integer;
begin
b:=a;
repeat
t:=Filtr(b);
d:=length(t)-length(b); // количество отсеянных
b:=t;
until d=0;
// вывод
memo2.Clear;
for i:=low(b) to high(b) do
memo2.lines.add(floattostr(b[i]));
Так вот этот repeat "съедает" весь массив! И как его остановить вовремя - я не знаю. А в этом, в принципе, было бы решение проблемы.
abun (2009-08-11 10:11:00) [11]Немножко не то... Мы пишем прогу мониторинга обменных пунктов. Разработку можно наблюдать здесь: http://www.bestchange.info/ru/download/counter.php?id=1(ссылка для скачивания)
http://www.bestchange.info/prog.html(ссылка на описание программы)
Парсер на РНР, который занимается обработкой файлов курсов валют, пока не идеален, поэтому нужна вот такая очистка.
А привязка лишняя - в данном случае к Центробанку - не желательна, но в этом, возможно, и есть доля логики. Главная проблема, что там не найдутся курсы электронных валют (например, вебмани, дельтакей и др.)
Вариант (2009-08-11 09:15:00) [12]
> abun © (10.08.09 22:18) [19]
Вообще-то для приведенного набора медианный фильтр прекрасно отработал, если медиану использовать для поиска "среднего", которое возьмем за якорь.
Приведу примерные шаги алгоритма
Есть список курсов валют
Дано
[90,100,2100,2120,2130,2135,2140,2160,2200,2300,2500,3500,4000,100000].
В данном случае список сортирован, но не будем закладываться на то, что получим сортированный список. А для медианной фильтрации надо работать с сортированным списком (массивом)
1)
сортируем массив
2)
Определим медиану. Медиана это центральный эелемент отсортированного массива (в случае четного числа элементов я беру ближайший к центру с меньшим индексом)
В нашем случае это 2140
3) В списке оставим только те элементы, отклонение которых от медианы не превышет 20% (или сколько надо) Res=100.0*abs(E-Med) /Med, где E - проверяемый элемент массива, а Med наша медиана, а Res отклонение от медианы и мы задались, что Res <= 20%.
В результате получим [2100,2120,2130,2135,2140,2160,2200,2300,2500], а отсеянные элементы [90,100,3500,4000,100000]
Теперь о курсе валют, есть вопрос - почему бы не получать курс например Центробанка и его не брать за основу(а не медиану), от которой допустимы отклонения на ту или иную величину?
Дмитрий Белькевич (2009-08-11 00:51:00) [13]
> И эти курсы иногда с ошибками - хотелось бы их фильтровать
> в автоматическом режиме.
Пойдём другим путём. Откуда вообще известно, что данные ошибочны? Может проще каждое число на верность каким-то образом проверить или таки получить изначально верные данные?
Дмитрий Белькевич (2009-08-11 00:47:00) [14]
> Но если на конце будет два "левых" числа - фильтр не работает.
> :(
Два раза последовательно проходить не пробовал?
Сергей М. (2009-08-11 00:20:00) [15]
> курсы иногда с ошибками
> критерий Стьюдента не работает
> Пробуем медианный алгоритм
> Тоже не ахти
Ну вот нам и еще один новоявленный премьер-министр - курсы щелкает-пересчитвает как белка орехи : куда кривая-нелегкая выведет, туда и ..
)
abun (2009-08-10 22:18:00) [16]Тоже не ахти. Съедает только крайние элементы. Но если на конце будет два "левых" числа - фильтр не работает. :(
abun (2009-08-10 22:03:00) [17]Итак, проверено: критерий Стьюдента не работает в данном случае.
Пробуем медианный алгоритм.
Дмитрий Белькевич (2009-08-10 21:45:00) [18]для трёх чисел:
function Med(a, b, c: integer): integer;
var
t: Integer;
begin
if (a > b) then
begin
t := a;
a := b;
b := t;
end;
if (b > c) then
b := c;
if (a > b) then
result := a
else
result := b;
end;
Этим последовательно пройтись по всему массиву, помещая результат в новый массив:
for j := LeftBorder + 1 to RightBorder - 1 do
lBuff8[j] := Med(FBuff8[j - 1], FBuff8[j], FBuff8[j + 1]);
Единичные выбросы эффективно режет, при этом не 'блюрит' данные/картинку.
abun (2009-08-10 21:28:00) [19]Читал, но не понял, как ее реализовывать.
Дмитрий Белькевич (2009-08-10 21:01:00) [20]Может медианную фильтрацию попробовать?