Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Алгоритмы > Оцените реализацию алгоритма свертки. |
Автор: inamozov 2.5.2012, 01:00 | ||
Здравствуйте! Краткое описание: Передо мной стояла задача реализовать алгоритм дискретной свертки двух сигналов, не прибегая к какой-либо внешней помощи. Я свел задачу к вычислению всех диагоналей произвольной (в общем случае) матрицы и получил решение. Я новичек и было бы здорово услышать Вашу оценку и критику Алгоритм: Имеются два одномерных числовых массива(arrayX, arrayH) произвольной длины (N и M), которые почленно (x1 * (h1, h2, ..., hm), x2 * (h1, h2,...,hm), ...) перемножаются в матрицу размера [NxM]. Таким образом матрица будет содержать все слагаемые для свертки (в процессе свертки каждый элемент одного массива перемножается с каждым элементом другого массива). Таким образом каждая диагональ получившейся матрицы будет представлять собой элемент свертки, так что задача как раз сводится, в моем случае, к вычислению всех диагоналей данной матрицы. Подсчет диагоналей осуществляется от левого верхнего элемента, то есть, если мы имеем матрицу: 1 2 3 4 5 6 7 8 9 То диагонали будут соответственно: 1, 2 + 4, 3 + 5 + 7, 6 + 8, 9
Примечания: В тексте кода расчитываются не все диагонали матрицы, а только верхняя их часть. Для расчета диагоналей нижней части и получения полного решения, достаточно транспонировать имеющуюся матрицу и снова применить к ней этот же алгоритм. |
Автор: ksili 2.5.2012, 03:32 |
Топик на этом форуме является обращением к внешней помощи ![]() Зачем промежуточные произведения сводить в матрицу, забивать память? Суммируй их сразу. |
Автор: inamozov 2.5.2012, 15:42 |
ksili, хех, спасибо! Вообще меня более всего интересует, насколько хорош выбранный мной путь решения такой задачи? А, в целом, сведение аналитиеской задачи к операциям над матрицей довольно распространенная практика... Но не могу не согласиться что вставлять промежуточную матрицу в код это была лишняя нагрузка. Думаю, стоит такие действия выполнять на бумаге, а в код забивать уже более концентрированную идею. |
Автор: volatile 2.5.2012, 23:59 |
inamozov, не вникал в алгоритм. Просто брасается в глаза. Здесь j никогда не будет равно m |
Автор: inamozov 3.5.2012, 00:15 |
volatile, спасибо, это (!(j == m)) надо вообще убирать. надеюсь скоро довести до одного общего, без транспонирования довел |
Автор: ksili 4.5.2012, 09:19 |
зачем без транспонирования? можно вообще без матрицы. |
Автор: DRUID3 17.5.2012, 22:25 |
Сколько не видел FFT, FWT и прочих реализаций матпреобразований - все они в чем-то разные, а ведь кажется математика это нечто общее для всех... ![]() Одномерную свертку я представляю так как когда-то ее объяснил один преподаватель "радиотехнических сигналов и систем" - берем два графика, один обращаем вспять(как если бы перевернули лист на другую сторону) и поточечно перемножаем и суммируем(вот почему умножение с накоплением основная операция в DSP). Сдвигаем графики навстречу друг другу на одну точку и снова повторяем... И так бесконечно. ![]() Прилагаю маленький проектик FIR-фильтра(та же свертка). P.S.: ...я не говорю, что у топикстартера идея/реализация неверно(я не проверял ![]() P.P.S.: если в комментах грамматические оПшиПки - сообщите - это да, грамАта ниККаДДа не Пыла мАим сильным местАм ![]() |
Автор: ksili 18.5.2012, 04:24 |
Бесконечно - это в циклической свёртке. А так, длина результирующей последовательности равна N+M-1. |
Автор: inamozov 18.5.2012, 06:27 | ||
Вот вариант, от 2.05.2012, где происходит подсчет диагоналей (гипотетической ![]() В итоге цельный алгоритм реализован путем обхода по матрице слева направо а потом сверху вниз.
|
Автор: volatile 19.5.2012, 00:55 |
Есть такое понятие, http://ru.wikipedia.org/wiki/%D0%91%D1%80%D0%B8%D1%82%D0%B2%D0%B0_%D0%9E%D0%BA%D0%BA%D0%B0%D0%BC%D0%B0, соблюдение которого еще никому никогда не помешало. Зачем здесь столько нагорожено? Нужно быть проще, задача то элементарная. (см. мой пост выше.) Сами не разберетесь в своем коде через пару месяцев. К тому-же, чисто по опыту скажу: очень вероятно, что в такой мешанине не один баг зарыт. |
Автор: inamozov 19.5.2012, 05:40 | ||
volatile, стараюсь придерживаться принципа доводить начатое до конца. Ваш алгоритм:
замечательно прост и красив, только еще не было времени "разобраться" с ним. Спасибо. |
Автор: volatile 19.5.2012, 23:00 | ||
inamozov, на самом деле, там много времени не нужно. Попробую объяснить. Например, возьмем ячейку sum[0] В ней будет сумма тех элементов, чьи индексы дают в сумме 0. Таких элементов, как не трудно догадаться, всего один, это matrix[0][0]; это наша первая диагональ, которая состоит из одной клетки (0,0) возьмем ячейку sum[1] В ней будет сумма тех элементов, чьи индексы дают в сумме 1. Таких элементов, уже два, это matrix[0][1], и matrix[1][0]; это наша 2-я диагональ, которая состоит из 2-ух клеток (0,1) (1,0) возьмем ячейку sum[2] В ней будет сумма тех элементов, чьи индексы дают в сумме 2. Таких элементов, уже 3, это matrix[0][2], matrix[1][1], и matrix[2][0]; это наша 3-я диагональ, которая состоит из 3-ех клеток (0,2) (1,1) (2,0) Ну и так далее... Для матрицы 4*4, например вся картина будет такой:
Все ведь просто. ![]() |
Автор: inamozov 21.5.2012, 12:09 |
volatile, у меня возник к Вам вопрос: получается, что Ваш алгоритм оперирует не самой реализацией матрицы - ее елементами (как делал я), а, скорее, на уровне свойств этой матрицы - в данном случае порядковых номеров элементов. Посоветовали бы вы при операциях над матрицами строить алгоритмы на уровне свойтв этих сущностей не "опускаясь" до их реализации? |
Автор: volatile 22.5.2012, 01:08 | ||||
Ну почему же. Алгоритм оперирует именно элементами. Проходит их все, от первого до последнего. Ну и да, при этом использует свойство индексов. ![]()
Даже не знаю что ответить... Единого рецепта видимо нет. Больше программируйте, больше изучайте чужие программы. С опытом придет понимание что лучше в конкретном случае. ![]() |
Автор: ksili 22.5.2012, 05:51 |
inamozov, я в разных книгах видел описание свёртки и НИГДЕ не приводится всё к матрице. Обычно - рисунок, или формула, которые сводятся к тому алгоритму (коду), который привёл volatile. Так что мне кажется, это вы всё усложняете, а не volatile. |
Автор: DRUID3 23.5.2012, 02:54 | ||||
1)А кто сказал, что свертка это матричная операция? В непрерывных сигналах там ее вообще нет. Матрицу просто вводят для удобства - причем удобства понимания, причем ( ![]() 2) первая задача при написании матопераций их верификация(обязательно), вторая их оптимизация(тем ценнее алгоритм). Свертка задача - однозначная. Потому писать ее нужно как можно проще, не добавляя новых сущностей. Кстати еще - в Вашем коде много if()-ов а они сбрасывают кэш, а это замедляет работу программы на порядки!!! Правда у Вас джава, а я не знаю какова там внутренняя кухня.
http://www.dsplib.ru/content/conv/conv.html. Препод кстати об обычной рассказывал - интегрируем то мы откуда докуда? Просто ненулевой результат будет для N+M-1 конечно. P.S.: никто так и не скачал мой фильтр, а я то думал послать код в "эпл" и затребовать миллион... ![]() |