Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Фильтрация массива чисел от шума


Страницы:   1 2

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]

Может медианную фильтрацию попробовать?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо