приближение логарифма с использованием гармонического среднего

Вопрос или проблема

вот функция для аппроксимации log10(x+1), (x+1) < ~1.2

a = 1.097
b = 0.085
c = 2.31

ans = 1 / (a - b*x + c/x)

так это должно выглядеть
она работает, подстраивая среднее гармоническое, чтобы соответствовать log10
но проблема в значениях abc

вопрос в том, как получить подходящие a, b и c
и как сделать лучшее приближение

я написал этот код, который может дать вам довольно хорошее приближение для a, b, c
но мой код не смог сделать это лучше

вот мой код:

import numpy as np

a = 1
b = 0.01
c = 2

def mlg(t):
    x = t
    if t == 0:
        x = 0.00000001
    x2 = x*x
    o = a - (b * x) + (c / x)
    return 1/o

def mlg0(t):
    x = t
    if t == 0:
        x = 0.00000001
    x2 = x*x
    o = a - (b * x) + (c / x)
    return o

for i in range(9000):
    n1 = np.random.uniform(0,1.19,1000)
    for i in range(1000):
        n = n1[i]
        o = np.log10(n+1)
        u = mlg(n) - o
        e = u ** 2

        de_da = 0 - 2 * (u) / (mlg0(n) ** 2)
        de_db = de_da * n 
        de_dc = de_da / n

        a -= de_da * 0.00001
        b -= de_db * 0.00001
        c -= de_dc * 0.00001

print(a,b,c)

так что у вас есть какие-либо идеи, как сгенерировать лучшие значения?

я использовал метод, похожий на обратное распространение в НН, но он не смог дать мне значения лучше

Ответ или решение

Приближение логарифма с использованием среднеарифметического: Настройка параметров

Приближение функции логарифма, такой как (\log_{10}(x + 1)) для ( (x + 1) < \sim 1.2 ), с использованием выражения:

[
\text{ans} = \frac{1}{a – b \cdot x + \frac{c}{x}}
]

может быть эффективным, если правильно подобрать значения параметров (a), (b) и (c). Данный подход использует гармоническое среднее для настройки приближения к логарифмической функции, однако, как вы отметили, подходящие значения этих параметров не очевидны.

Постановка задачи

Наша цель — оптимизировать значения (a), (b) и (c) так, чтобы минимизировать ошибку между приближением и реальным значением логарифма для заданного диапазона (x). Ваш код применяет случайные выборки и градиентный спуск, но по всей видимости не дает ожиданий улучшения.

Подход к решению задачи

  1. Целевая функция:
    Мы можем определить целевую функцию как сумму квадратов ошибок между истинным значением (\log_{10}(x + 1)) и вашим приближением для множества значений (x). Это позволит нам найти минимальные значения для параметров.

    [
    E(a, b, c) = \sum{i=1}^{N} \left( \log{10}(x_i + 1) – \frac{1}{a – b \cdot x_i + \frac{c}{x_i}} \right)^2
    ]

    где (x_i) — это значения (x) в диапазоне от (0) до (1.19).

  2. Оптимизация методом градиентного спуска:
    Подход, который вы используете, уже включает элементы градиентного спуска, но мы можем улучшить его, добавив вычисление градиента по всем параметрам одновременно, и применив адаптивные методы, например, Adam или RMSprop, для улучшения сходимости.

  3. Алгоритм:
    Вы можете использовать следующий процесс:

    • Сгенерировать выборку значений (x) из диапазона (0) до (1.19).
    • Для каждого значения вычислить ошибку.
    • Обновить параметры (a), (b) и (c) на основании градиентов, рассчитанных по по всем данным сразу.
import numpy as np

# Начальные параметры
a = 1.0
b = 0.01
c = 2.0

def mlg(x):
    if x == 0:
        x = 1e-10 # Защита от деления на ноль
    return 1 / (a - b * x + c / x)

def compute_error(n_samples=1000):
    x_samples = np.random.uniform(0, 1.19, n_samples)
    log_values = np.log10(x_samples + 1)
    approx_values = np.array([mlg(x) for x in x_samples])
    return np.mean((log_values - approx_values) ** 2)

learning_rate = 0.00001
for _ in range(10000): # Итерации оптимизации
    error = compute_error()

    # Обратный пропуск – оценка градиента:
    de_da, de_db, de_dc = 0, 0, 0 # Начальные значения градиентов
    for x in np.random.uniform(0, 1.19, 1000):
        actual = np.log10(x + 1)
        approx = mlg(x)
        u = approx - actual
        o = a - b * x + c / x

        # Здесь находим градиенты
        de_da -= 2 * u / o**2
        de_db -= 2 * u * x / o**2
        de_dc -= 2 * u / (o * x)

    # Обновление параметров
    a -= learning_rate * de_da / 1000
    b -= learning_rate * de_db / 1000
    c -= learning_rate * de_dc / 1000

print(a, b, c)

Заключение

Используя данные методы, вы сможете получить более точные и надежные значения для параметров (a), (b) и (c). Чем больше выборка, тем точнее будет ваше приближение. Оптимизация логарифмической функции требует тщательного подхода, и адаптация базовых методов градиентного спуска с учетом всех данных может существенно повысить результативность.

Оцените материал
Добавить комментарий

Капча загружается...