Адаптивный контроль усиления с алгоритмом наименьших средних квадратов

Адаптивный контроль усиления с алгоритмом наименьших средних квадратов
Адаптивный контроль усиления с алгоритмом наименьших средних квадратов
Anonim

Адаптивный контроль усиления с использованием алгоритма наименьших средних квадратов

Вот трюк, который вы буквально никогда не будете использовать, если не используете микропроцессор, который вы купили для долей фракций центов. Возможно, вы даже захотите рассчитать, сколько определенного количества этих микроконтроллеров приходится на единицу вашего устройства микроконтроллер, но вы не можете, потому что он настолько дешев, что даже не может делить. Этот метод разделения представляет собой введение в адаптивный контроль усиления с квадратичным алгоритмом наименьших квадратов, который, как я думаю, прольет свет на работу того, как итеративный процесс рассчитывает желаемую прибыль. Взгляните на следующий код Matlab, который будет сходиться к правильному значению, которое вы пытаетесь разделить (без использования оператора деления).


DivideBy = 5; mu =.1; DivideByFactor = 1; ref = 1; num_iter = 20 for n = 1:num_iter y(n) = DivideBy * DivideByFactor; y_mag = abs(y(n)); err(n) = ref - y_mag; DivideByFactor_time(n) = DivideByFactor; DivideByFactor = DivideByFactor +mu*err(n); end

Это оно! Деление на 12 строк кода без оператора деления. Этот алгоритм получен из адаптивного или автоматического алгоритма управления усилением (AGC), используемого для поддержания определенной амплитуды на выходе системы, несмотря на изменения амплитуды на входе системы. Например, в аудиосистеме AGC может уменьшить громкость, если сигнал становится слишком большим и увеличивать его, если сигнал становится слишком маленьким.

В цифровом домене диаграмму системы можно увидеть на рисунке 1. Попробуйте мысленно следовать тому, как каждая итерация вышеперечисленного алгоритма перемещает сэмплы вокруг цикла.

Image
Image

Рисунок 1

AGC использует алгоритм наименьших квадратов (LMS) для обновления веса, называемого DivideByFactor в этой реализации. Этот алгоритм пытается минимизировать ошибку между выходом (y (n)) и ссылкой, которую мы установили в один. Опорный сигнал устанавливается равным единице, так что DivideBy * DivideByFactor = 1 после сближения алгоритма. Целые книги могут быть написаны на тему алгоритма LMS, поэтому я буду держать его в курсе. Нижняя ветвь петли может быть записана как:

$$ DivideByFactor (n) = DivideByFactor (n-1) + \ mu (ref-y (n)) $$

Эта строка в основном принимает небольшие шаги к числу, которое минимизирует ошибку:

$$ err (n) = ref-y (n) $$

Требуется шаг $$ \ mu $$ ошибки от DivideByFactor (который мы первоначально установили в 1 перед итеративным циклом). При достаточных шагах это идеально сходится к 1 / DivideBy, сводя к минимуму значение ошибки до нуля в процессе. Mu только стабилен в пределах определенного диапазона, который выходит за рамки этой статьи, но я приведу ссылки ниже, если вы хотите изучить его дальше. Вы можете проверить, как система ведет себя с разными значениями $$ \ mu $$, изменив параметр $$ \ mu $$ в коде. Уменьшая $$ \ mu $$, вы можете видеть, что для объединения в DivideByFactor требуется больше итераций. Если вы сделаете $$ \ mu $$ слишком большим, вы увидите, что DivideByFactor расходится и постоянно увеличивается (не хорошо).

Вы можете наблюдать, как DivideByFactor сходится к желаемому значению, включая следующий код, который отображает термин DivideByFactor_time для каждой итерации:


plot((1:num_iter), DivideByFactor_time) hold on plot((1:num_iter), 1/DivideBy, 'color', 'r') axis((0 num_iter -0.05 1)) grid on

Image
Image

В этом примере я установил DivideBy в 10 и построил график DivideByFactor_time для каждой итерации. Мы ожидаем, что он сходится к 0.10 (пунктирная красная линия), и мы видим, что после нескольких итераций он сходится довольно хорошо с желаемым значением. Если мы установим $$ \ mu $$ на что-то действительно маленькое, как 1/10 от его первоначального значения, мы увидим, что для достижения значения требуется больше времени для достижения желаемого значения

Image
Image

Попытайтесь изменить $$ \ mu $$ на что-то большое и обратите внимание на то, что происходит (вам может потребоваться расширить ось x и ось y, чтобы посмотреть ее поведение). Также попробуйте построить ошибку (n) против итераций, чтобы посмотреть, как она сходится к 0!

Вот и все - итеративный алгоритм деления, основанный на автоматическом управлении усилением. Если у вас нет Matlab, попробуйте запустить это в Octave, который является открытым исходным кодом и почти точно совпадает с языком Matlab (минус некоторые функции). Если вы не хотите загружать Octave, попробуйте портировать коды выше на ваш любимый язык и включить его в комментарии ниже для других, чтобы поиграть с! Обратите внимание: если вы не получаете правильные значения, вам, вероятно, нужно увеличить количество итераций!

Для дальнейшего чтения в алгоритме LMS проверьте это.