Вопрос или проблема
вот функция для аппроксимации 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). Ваш код применяет случайные выборки и градиентный спуск, но по всей видимости не дает ожиданий улучшения.
Подход к решению задачи
-
Целевая функция:
Мы можем определить целевую функцию как сумму квадратов ошибок между истинным значением (\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).
-
Оптимизация методом градиентного спуска:
Подход, который вы используете, уже включает элементы градиентного спуска, но мы можем улучшить его, добавив вычисление градиента по всем параметрам одновременно, и применив адаптивные методы, например, Adam или RMSprop, для улучшения сходимости. -
Алгоритм:
Вы можете использовать следующий процесс:- Сгенерировать выборку значений (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). Чем больше выборка, тем точнее будет ваше приближение. Оптимизация логарифмической функции требует тщательного подхода, и адаптация базовых методов градиентного спуска с учетом всех данных может существенно повысить результативность.