Flashback bygger pepparkakshus!
2025-06-28, 13:13
  #1
Medlem
Håller på med programmering av ett enklare program för eget bruk (ej skoluppgift), men matematiken som krävs ligger lite över min kunskapsnivå. Har bett AI om hjälp, men den fepplar all-over-the-place hela tiden, så jag tänkte fråga om lite handledningshjälp i rätt riktning här, för den som har lust.

Sammanhanget är digital signalprocessning (ljud).
Jag behöver kompensera varje given frekvens (Hz) med ett visst värde (vi kan kalla det "jämkningsvärdet"), för att funktionen jag utvecklar ska fungera som den ska. Det finns ingen annan väg runt problemet, som jag ser.

Jag tog fram jämkningsvärdet för varje frekvens. Syns i listan nedan, frekvensen till vänster, jämkningsvärdet till höger.

100hz - 240
200hz - 138
300hz - 100,5
400hz - 83
500hz - 71,5
600hz - 64
700hz - 58
800hz - 54
900hz - 50,5
1000hz - 47,5

Jag har uppmätt jämkningsvärdet mellan 100-1000hz, i hopp om att det intervallet torde räcka för att klura ut potensslaget eller iaf den faktor som jämkningsvärdet utgör jämte frekvenserna. Målsättningen är att kunna tillämpa detta över hela det hörbara frekvensregistret (20Hz-20000Hz) genom att räkna ut vilken "faktor" (el dyl) som frekvensen måste beräknas genom för att få fram jämkningsvärdet programmatiskt.

Uppmätningarna av jämkningsvärdet är tämligen precis, men har avrundats något, så utrymme för varianser på +/- 2 finns. +/-3 eller mer räknas tyvärr som mycket, i min tillämpning. Så det är ganska tajt.

Enkelt uttryckt: om jag vrider på reglaget för frekvens (i GUI), så vill jag jämkningsvärdet ska beräknas - programmatiskt - utifrån frekvensen och lagras i egen variabel. Jämkningsvärdena i variabeln är alltså frekvensberoende och måste använda en potential som får dom att stämma med alla värden mellan 100hz-1000hz ovan, och i förlängningen alla andra frekvenser inom 20-20000hz.
Uttryckt i kod,ungefär såhär:
Kod:
jämkningsvärde = frekvens ? potens-kalkyl;
resultat = 10^(annat_värde / jämkningsvärde);
Problemet är att det ligger precis bortom min förmåga. AI säger sig ha hittat minst 2 olika sätt att förklara potensförhållandet på, som ska stämma väldigt rätt. Men när man tillämpar dom lösningarna AI föreslår så fungerar förvisso uträkningen, men jämkningsvärdet blir ibland upp till 50 siffror fel. När man ifrågasätter detta börjar AI sen filibustra sönder sig själv och svaren tills inget fungerar längre. Och där står jag fast.
Jag är helt säker på att ingen utomstående annan faktor inverkar i uträkningen av misstag.

Här är AI loggen för den bästa av AIs förslag, som - som sagt - leder till jämkningsvärden som är rejält off, men kanske kan vara till understödande hjälp:
Kod:
Let me solve for k and n using logarithms:
Taking the natural log of both sides:
ln(jamkningsvarde) = ln(k) - n × ln(frequency)
Using two well-spaced points (100Hz and 1000Hz):

100Hz: ln(240) = ln(k) - n × ln(100)
1000Hz: ln(47.5) = ln(k) - n × ln(1000)

Solving:
ln(240) ≈ 5.48, ln(100) ≈ 4.61
ln(47.5) ≈ 3.86, ln(1000) ≈ 6.91

From these: n ≈ 0.70, k ≈ 4750

Proposed formula:
jamkningsvarde = 4750 / frequency ^ 0.7
Let me verify this against your data points:

100Hz: 4750/100^0.7 = 4750/19.95 ≈ 238 (actual: 240)
200Hz: 4750/200^0.7 = 4750/34.23 ≈ 139 (actual: 138)
400Hz: 4750/400^0.7 = 4750/58.77 ≈ 81 (actual: 83)
600Hz: 4750/600^0.7 = 4750/78.11 ≈ 61 (actual: 64)
800Hz: 4750/800^0.7 = 4750/95.59 ≈ 50 (actual: 54)
1000Hz: 4750/1000^0.7 = 4750/100.00 ≈ 48 (actual: 47.5)

The fit is very close!

Final implementation:
jamkningsvarde = 4750 / pow(frekvens, 0.7);
uträkning = 10^(annat_värde / jamkningsvarde);
Jag tror inte jag lyckas lösa det här själv, och är även förvånad hur abstrakt AI är angåenden sina egna lösningar. Skulle hemskt gärna uppskatta hjälp i vart problemet sitter eller vad som verkar gå fel här. Har AI fuckat up, eller är det översättningen till syntax som gör att det blir fel?
(Koden är EEL v2, Extensible Embeddable Language, förenklad version av C).

Tackar väldigt mycket för hjälp. Utan den här lösningen är över 14 dagars jobb förgäves.
/Marinerad (just vad man känner sig som nu).
__________________
Senast redigerad av Marinerad65 2025-06-28 kl. 13:25.
Citera
2025-06-28, 13:53
  #2
Bannlyst
Sätt f(x) = a + bx^n

Interpolera.

Svar: 2669.67 - 2145.58x^0.0300407

Använd inte AI. AI fabulerar och hallucinerar och kan aldrig lösa sådana härproblem.
Citera
2025-06-28, 15:58
  #3
Citat:
Ursprungligen postat av VoldemortZelenskyj
Sätt f(x) = a + bx^n

Interpolera.

Svar: 2669.67 - 2145.58x^0.0300407

Använd inte AI. AI fabulerar och hallucinerar och kan aldrig lösa sådana härproblem.



Jag kastade själva interpoleringen på gemini-2.5-pro genom Gemini CLI och bad den implementera detta i python, detta är resultatet:

Kod:
import numpy as np

# --- Data ---
# Frequencies (in Hz)
frequencies = np.array([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000])
# Corresponding values
values = np.array([240, 138, 100.5, 83, 71.5, 64, 58, 54, 50.5, 47.5])

# --- Interpolation ---

# Example 1: Interpolate a single value
# You can change this value to find the corresponding interpolated value.
frequency_to_find = 250
interpolated_value = np.interp(frequency_to_find, frequencies, values)

print(f"Interpolated value at {frequency_to_find}hz: {interpolated_value:.2f}")

Claude som brukar vara bra på kod (körde Claude 4 via web interface, ej Claude code) presenterade ett lite väl omfattande svar med snygga plottar, jämförelser av värdena för olika typer av interpolering och lite annat lull-lull.

Detta utgör kanske ett exempel på att man ofta kan använda ai framgångsrikt för delproblem, men den lallar gärna iväg om scopet är för stort?
__________________
Senast redigerad av output-crop-clash 2025-06-28 kl. 16:03.
Citera
2025-06-28, 18:57
  #4
Medlem
Smekarn87s avatar
Vad ska maskinen göra egentligen. Vad gör du om du får in frekvensen 131hz? Hur hanterar du att en monokanal ljud kan ta in ett ljud med flera på varandra lagda frekvenser/toner? Hur gör du om du får in interferensen av tonen c och a?
Citera
2025-06-29, 19:32
  #5
Medlem
Chatgpt löser detta på ett kick men jag tror man måste välja modell med litet omsorg.

Efter att ha prövat litet olika så verkade f(x) = a*ln(x) + (b/x)*e^(-cx) rätt ok ändå.

Uppskattade värden:
a = 3.006186 ± 0.047222 (95% CI)
b = 23726.0221 ± 8.5289 (95% CI)
c = -0.000158 ± 0.000012 (95% CI)
Maximum estimated absolute y-value error over x=20 to 20,000: 7.2266
Occurs at x = 20000.00
Maximum estimated relative y-value error: 12.55%
Occurs at x = 20000.00

Det var problematiskt att hitta en modell som inte urartade vid låga eller höga frekvenser. Därför viktade jag så att modellen tog större hänsyn till de angivna värdena med hög frekvens(utan viktning "exploderade" uppskattade fel för höga frekvenser).

Att införa en fjärde variable skulle enligt chatgpt kraftigt öka risken för overfittting.

Python-kod:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.stats import t

# Data points
frequencies = np.array([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000])
values = np.array([240, 138, 100.5, 83, 71.5, 64, 58, 54, 50.5, 47.5])

# Model function: y = a*ln(x) + (b/x)*exp(-c*x)
def model(x, a, b, c):
return a * np.log(x) + (b / x) * np.exp(-c * x)

# Weighting: emphasize large frequencies
weights = frequencies
sigma = 1 / weights # smaller sigma → higher weight for large freq

# Fit model with weighting
params, covariance = curve_fit(
model,
frequencies,
values,
sigma=sigma,
absolute_sigma=True,
p0=(1, 10000, 0.005)
)
a_fit, b_fit, c_fit = params
errors = np.sqrt(np.diag(covariance))

# Degrees of freedom and t-value for 95% confidence interval
n = len(frequencies)
p = len(params)
dof = max(0, n - p)
t_val = t.ppf(0.975, dof)

# 95% confidence intervals
ci_a = t_val * errors[0]
ci_b = t_val * errors[1]
ci_c = t_val * errors[2]

print(f"a = {a_fit:.6f} ± {ci_a:.6f} (95% CI)")
print(f"b = {b_fit:.4f} ± {ci_b:.4f} (95% CI)")
print(f"c = {c_fit:.6f} ± {ci_c:.6f} (95% CI)")

# Function to calculate error bands from parameter uncertainties
def error_band(x, a, b, c, da, db, dc):
dy_da = np.log(x)
dy_db = np.exp(-c * x) / x
dy_dc = -b * np.exp(-c * x)
return np.abs(dy_da * da) + np.abs(dy_db * db) + np.abs(dy_dc * dc)

# Evaluate fit and error over a broad range
x_range = np.linspace(20, 20000, 1000)
y_fit = model(x_range, a_fit, b_fit, c_fit)
y_err = error_band(x_range, a_fit, b_fit, c_fit, ci_a, ci_b, ci_c)

# Max absolute error and corresponding x
max_error = np.max(y_err)
max_error_x = x_range[np.argmax(y_err)]

print(f"Maximum estimated absolute y-value error over x=20 to 20,000: {max_error:.4f}")
print(f"Occurs at x = {max_error_x:.2f}")

# Max relative error (%) safely (avoid divide by zero)
rel_error_pct = 100 * (y_err / np.abs(y_fit))
rel_error_pct = np.where(np.abs(y_fit) > 1e-10, rel_error_pct, 0)

max_rel_error_pct = np.max(rel_error_pct)
max_rel_error_x_pct = x_range[np.argmax(rel_error_pct)]

print(f"Maximum estimated relative y-value error: {max_rel_error_pct:.2f}%")
print(f"Occurs at x = {max_rel_error_x_pct:.2f}")

# Plot data, fit, and confidence interval
plt.figure(figsize=(10, 6))
plt.plot(frequencies, values, 'bo', label='Original Data')
plt.plot(x_range, y_fit, 'm--', label='Fitted Curve')
plt.fill_between(x_range, y_fit - y_err, y_fit + y_err, color='m', alpha=0.2, label='95% Confidence Interval')
plt.title('Fit: y = a*ln(x) + (b/x)*exp(-cx) (weighted to large freq)')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Value')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()


Tror man behöver fler värden eller också fippla manuellt med värden för de högsta frekvenserna för att få en riktigt bra träff.
Citera
2025-06-29, 22:24
  #6
Medlem
Citat:
Ursprungligen postat av VoldemortZelenskyj
Sätt f(x) = a + bx^n

Interpolera.

Svar: 2669.67 - 2145.58x^0.0300407
Tackar så mycket. Ska testa det här nu.
Skulle vara väldigt intressant att se hur man kan räkna ut på förhand att just interpolations-uppställningen f(x) = a + bx^n kan formulera rätt resultat. Men man kanske provar sig fram med lite olika modeller och/eller interpolationsmetoder?

Provkörde 2669.67 - 2145.58x^0.0300407 genom EEL syntaxen
Kod:
jämkningsvärde = 2669.67 - 2145.58 * pow(frekvens, 0.0300407);
resultat = 10^(annat_värde / jämkningsvärde);
Resultaten är långt mer stabila förhållanden än AI rekommenderade , även om jag känner mig otacksam som säger att resultaten ligger överlag lite för långt bort ifrån önskade värdena mellan 100-1000hz.

100hz - önskat: 240 - resultat: ~205
200hz - önskat: 138 - resultat: ~154
300hz - önskat: 100.5 - resultat: ~123
400hz - önskat: 83 - resultat: ~101
500hz - önskat: 71.5 - resultat: ~84
etc

Men det är nog förbaskat svårt även för ren matematik att träffa in perfekt rätt, eftersom skillnaderna mellan värdemängderna inte är helt proportionerliga. Man kommer nog bli tvungen att justera eller väga in något för att få det här att funka. Såg just att Chokladmums gjort det, så jag ska kika på det nu.
Citat:
Ursprungligen postat av VoldemortZelenskyj
Använd inte AI. AI fabulerar och hallucinerar och kan aldrig lösa sådana härproblem.
Ja som jag upplevde det så var AIn (Claude gratis i det här fallet) väldigt skum. Eftersom matten är lite ovanför min förmåga, så hade man inget sätt att verifiera metoden/värdena på än att testa helhetslösningen. När det inte stämde, så räknade Claude om igen, på ett annat sätt, som fuckade upp slutresultatet ännu mer, men Claude själv var ännu mer säker på sin sak. Den gav sig aldrig in på vad som kunde vara fel, ifrågasatte inte min tillämpning eller syntax eller om annan kod förvred resultaten eller om jag ställt in kodmiljön på ett skumt sätt, ingenting .. utan räknade bara om hela tiden.
Citat:
Ursprungligen postat av Smekarn87
Vad ska maskinen göra egentligen. Vad gör du om du får in frekvensen 131hz? Hur hanterar du att en monokanal ljud kan ta in ett ljud med flera på varandra lagda frekvenser/toner? Hur gör du om du får in interferensen av tonen c och a?
Det är equalizer, och jag vill göra lite specialare med den efter specifikt behov. Inget standard. Just den här detaljen är bara att ta frekvensen som filtret är inställt på för stunden, och räkna ut ett annat värde - det jag kallar jämkningsvärdet - ifrån frekvensen, och tillämpa det på signalbehandlingen på lite speciella sätt, för speciella behov. Jämkningsvärdet, som jag kallar det här, är direkt avhängig av frekvensreglaget, så det kommer inte spela nån roll vilken frekvens man har ställt in.

Det var bara lite brant överkurs för mig att räkna ut vilken potens som jämkningsvärdet ska motsvara, för att stämma över hela frekvensregistret.
__________________
Senast redigerad av Marinerad65 2025-06-29 kl. 23:23.
Citera
2025-06-30, 19:16
  #7
Medlem
Citat:
Ursprungligen postat av Chokladmums
Chatgpt löser detta på ett kick men jag tror man måste välja modell med litet omsorg.

Efter att ha prövat litet olika så verkade f(x) = a*ln(x) + (b/x)*e^(-cx) rätt ok ändå.

Uppskattade värden:
a = 3.006186 ± 0.047222 (95% CI)
b = 23726.0221 ± 8.5289 (95% CI)
c = -0.000158 ± 0.000012 (95% CI)
Maximum estimated absolute y-value error over x=20 to 20,000: 7.2266
Occurs at x = 20000.00
Maximum estimated relative y-value error: 12.55%
Occurs at x = 20000.00

Det var problematiskt att hitta en modell som inte urartade vid låga eller höga frekvenser. Därför viktade jag så att modellen tog större hänsyn till de angivna värdena med hög frekvens(utan viktning "exploderade" uppskattade fel för höga frekvenser).

Att införa en fjärde variable skulle enligt chatgpt kraftigt öka risken för overfittting.

Python-kod:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.stats import t

# Data points
frequencies = np.array([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000])
values = np.array([240, 138, 100.5, 83, 71.5, 64, 58, 54, 50.5, 47.5])

# Model function: y = a*ln(x) + (b/x)*exp(-c*x)
def model(x, a, b, c):
return a * np.log(x) + (b / x) * np.exp(-c * x)

# Weighting: emphasize large frequencies
weights = frequencies
sigma = 1 / weights # smaller sigma → higher weight for large freq

# Fit model with weighting
params, covariance = curve_fit(
model,
frequencies,
values,
sigma=sigma,
absolute_sigma=True,
p0=(1, 10000, 0.005)
)
a_fit, b_fit, c_fit = params
errors = np.sqrt(np.diag(covariance))

# Degrees of freedom and t-value for 95% confidence interval
n = len(frequencies)
p = len(params)
dof = max(0, n - p)
t_val = t.ppf(0.975, dof)

# 95% confidence intervals
ci_a = t_val * errors[0]
ci_b = t_val * errors[1]
ci_c = t_val * errors[2]

print(f"a = {a_fit:.6f} ± {ci_a:.6f} (95% CI)")
print(f"b = {b_fit:.4f} ± {ci_b:.4f} (95% CI)")
print(f"c = {c_fit:.6f} ± {ci_c:.6f} (95% CI)")

# Function to calculate error bands from parameter uncertainties
def error_band(x, a, b, c, da, db, dc):
dy_da = np.log(x)
dy_db = np.exp(-c * x) / x
dy_dc = -b * np.exp(-c * x)
return np.abs(dy_da * da) + np.abs(dy_db * db) + np.abs(dy_dc * dc)

# Evaluate fit and error over a broad range
x_range = np.linspace(20, 20000, 1000)
y_fit = model(x_range, a_fit, b_fit, c_fit)
y_err = error_band(x_range, a_fit, b_fit, c_fit, ci_a, ci_b, ci_c)

# Max absolute error and corresponding x
max_error = np.max(y_err)
max_error_x = x_range[np.argmax(y_err)]

print(f"Maximum estimated absolute y-value error over x=20 to 20,000: {max_error:.4f}")
print(f"Occurs at x = {max_error_x:.2f}")

# Max relative error (%) safely (avoid divide by zero)
rel_error_pct = 100 * (y_err / np.abs(y_fit))
rel_error_pct = np.where(np.abs(y_fit) > 1e-10, rel_error_pct, 0)

max_rel_error_pct = np.max(rel_error_pct)
max_rel_error_x_pct = x_range[np.argmax(rel_error_pct)]

print(f"Maximum estimated relative y-value error: {max_rel_error_pct:.2f}%")
print(f"Occurs at x = {max_rel_error_x_pct:.2f}")

# Plot data, fit, and confidence interval
plt.figure(figsize=(10, 6))
plt.plot(frequencies, values, 'bo', label='Original Data')
plt.plot(x_range, y_fit, 'm--', label='Fitted Curve')
plt.fill_between(x_range, y_fit - y_err, y_fit + y_err, color='m', alpha=0.2, label='95% Confidence Interval')
plt.title('Fit: y = a*ln(x) + (b/x)*exp(-cx) (weighted to large freq)')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Value')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()


Tror man behöver fler värden eller också fippla manuellt med värden för de högsta frekvenserna för att få en riktigt bra träff.
Den här modellen, fungerade så pass bra att "jämkningsvärdena" ligger väldans nära dom önskade.
Kod:
jämkningsvärde  = 3.006186 * log(frekvens) + (23726.0221 / frekvens) * exp(-(-0.000158) * frekvens);
resultat = 10^(annat_värde / jämkningsvärde);
Antar att den godtyckliga viktningen var 'av vikt'. Avvikelserna ifrån dom önskade värdena blir något större ju längre ner i frekvens man kommer, men inom godtagbara proportioner. Jag får tacka o bocka för hjälpen.

Att det var svårt att hitta rak linje, och känna behov av viktning och småjustering, beror nog mycket på att mätvärdena (jämkningsvärdena) är uppmätta med aningen grov metod, delvis lite lidande av avrundade decimaler.

Jag är inte van att hitta interpolationsmetoder, men har just lärt att MS Excel ska ha en instickningsmodul för kurvpassning, som jag tänker titta närmare på för framtida bruk.

Därför undrar jag, ödmjukast, om du (eller någon här) för stunden skulle kunna hjälpa mig med 1 sista interpolation, för en annan typ av filter, men annars samma tillvägagångssätt? Sen kommer jag inte besvära mer.

100hz - 405
200hz - 215
300hz - 155
400hz - 125
500hz - 106
600hz - 93
700hz - 84
800hz - 77
900hz - 71
1000hz - 68

Det här filtret (ovan) kommer bara nyttjas mellan typ 20hz - 1500hz, så viktning behöver inte nödvändigtvis stämma över hela registret här.
__________________
Senast redigerad av Marinerad65 2025-06-30 kl. 19:25.
Citera
2025-06-30, 22:05
  #8
Medlem
Citat:
Ursprungligen postat av Marinerad65
Den här modellen, fungerade så pass bra att "jämkningsvärdena" ligger väldans nära dom önskade.
Kod:
jämkningsvärde  = 3.006186 * log(frekvens) + (23726.0221 / frekvens) * exp(-(-0.000158) * frekvens);
resultat = 10^(annat_värde / jämkningsvärde);
Antar att den godtyckliga viktningen var 'av vikt'. Avvikelserna ifrån dom önskade värdena blir något större ju längre ner i frekvens man kommer, men inom godtagbara proportioner. Jag får tacka o bocka för hjälpen.

Att det var svårt att hitta rak linje, och känna behov av viktning och småjustering, beror nog mycket på att mätvärdena (jämkningsvärdena) är uppmätta med aningen grov metod, delvis lite lidande av avrundade decimaler.

Jag är inte van att hitta interpolationsmetoder, men har just lärt att MS Excel ska ha en instickningsmodul för kurvpassning, som jag tänker titta närmare på för framtida bruk.

Därför undrar jag, ödmjukast, om du (eller någon här) för stunden skulle kunna hjälpa mig med 1 sista interpolation, för en annan typ av filter, men annars samma tillvägagångssätt? Sen kommer jag inte besvära mer.

100hz - 405
200hz - 215
300hz - 155
400hz - 125
500hz - 106
600hz - 93
700hz - 84
800hz - 77
900hz - 71
1000hz - 68

Det här filtret (ovan) kommer bara nyttjas mellan typ 20hz - 1500hz, så viktning behöver inte nödvändigtvis stämma över hela registret här.

Det visade sig svårt att få fram en y=f(x) funktion, för stor osäkerhet i olika koefficienter och, igen, för få datapunkter. Det som funkade bäst var ett filter, ger python-koden:

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import freqz

# Original data
freq = np.array([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000])
val = np.array([405, 215, 155, 125, 106, 93, 84, 77, 71, 68])

# Sampling frequency
fs = 2000 # You can adjust if needed

# Optimized IIR filter coefficients (from previous fitting)
b_opt = np.array([0.336, 0.294, 0.369, 0.187, -0.012])
a_opt = np.array([1.000, 0.100, 0.364, -0.335, -0.532])

# Define function y = f(frequency) using the IIR filter
def y_transfer_function(frequency_hz):
w = 2 * np.pi * frequency_hz / fs # Convert to digital angular frequency
_, h = freqz(b_opt, a_opt, worN=w)
return np.abs(h) * np.max(val) # Rescale to original amplitude

# Evaluate the function on the frequency points
y_tf_eval = y_transfer_function(freq)

# Plot original data and model response
plt.figure(figsize=(10, 5))
plt.plot(freq, val, 'o-', label='Original Data', color='black')
plt.plot(freq, y_tf_eval, 's--', label='y = f(frequency) (IIR Model)', color='darkorange')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Response')
plt.title('IIR Transfer Function Model Fit')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
Citera
2025-07-01, 23:30
  #9
Medlem
Citat:
Ursprungligen postat av Chokladmums
Det visade sig svårt att få fram en y=f(x) funktion, för stor osäkerhet i olika koefficienter och, igen, för få datapunkter. Det som funkade bäst var ett filter, ger python-koden:

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import freqz

# Original data
freq = np.array([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000])
val = np.array([405, 215, 155, 125, 106, 93, 84, 77, 71, 68])

# Sampling frequency
fs = 2000 # You can adjust if needed

# Optimized IIR filter coefficients (from previous fitting)
b_opt = np.array([0.336, 0.294, 0.369, 0.187, -0.012])
a_opt = np.array([1.000, 0.100, 0.364, -0.335, -0.532])

# Define function y = f(frequency) using the IIR filter
def y_transfer_function(frequency_hz):
w = 2 * np.pi * frequency_hz / fs # Convert to digital angular frequency
_, h = freqz(b_opt, a_opt, worN=w)
return np.abs(h) * np.max(val) # Rescale to original amplitude

# Evaluate the function on the frequency points
y_tf_eval = y_transfer_function(freq)

# Plot original data and model response
plt.figure(figsize=(10, 5))
plt.plot(freq, val, 'o-', label='Original Data', color='black')
plt.plot(freq, y_tf_eval, 's--', label='y = f(frequency) (IIR Model)', color='darkorange')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Response')
plt.title('IIR Transfer Function Model Fit')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
Aj då. Om man ökar antalet datapunkter, och noggrannare uppmätt denna gången?

Toleransen för varians i dom översta frekvenserna är mindre än +/- 1, medan toleransen för varians ökar progressivt tills dom lägsta frekvenserna, där toleransen är plus/minus flera hundra enheter.

(Hz - jämkningsvärde):

20 - 2000
30 - 1000
40 - 850
50 - 750
63 - 575
80 - 460
100 - 405
125 - 325
160 - 265
200 - 215
250 - 175
315 - 150
400 - 125
500 - 106
630 - 90
800 - 77
1000 - 68
1250 - 59,75
1600 - 52
2000 - 46,5
3000 - 38
4000 - 33
5000 - 30
6300 - 27,125
8000 - 24,25
Citera
2025-07-02, 14:03
  #10
Bannlyst
Man kan alltid få en exakt överensstämmelse genom att interpolera med ett polynom av grad n, där n är antalet punkter. Men en sådan lösning har mindre med verkligheten att göra, och funkar vanligen inte utanför definitionsmängden.
Citera
2025-07-02, 19:15
  #11
Medlem
Citat:
Ursprungligen postat av Marinerad65
Aj då. Om man ökar antalet datapunkter, och noggrannare uppmätt denna gången?

Toleransen för varians i dom översta frekvenserna är mindre än +/- 1, medan toleransen för varians ökar progressivt tills dom lägsta frekvenserna, där toleransen är plus/minus flera hundra enheter.

(Hz - jämkningsvärde):

20 - 2000
30 - 1000
40 - 850
50 - 750
63 - 575
80 - 460
100 - 405
125 - 325
160 - 265
200 - 215
250 - 175
315 - 150
400 - 125
500 - 106
630 - 90
800 - 77
1000 - 68
1250 - 59,75
1600 - 52
2000 - 46,5
3000 - 38
4000 - 33
5000 - 30
6300 - 27,125
8000 - 24,25

Hej igen, testade både filter och olika matematiska formler, det som funkade bäst för mig och chatgpt var följande modell:

F(x) = a*ln(x)*ln(x) +b*ln(x) +c.

Fick följande data för koefficienterna:

| Parameter | Estimate | 95% Confidence Interval |
| --------- | -------- | ----------------------- |
| **a** | −0.5015 | \[−0.5718, −0.4312] |
| **b** | 12.2293 | \[11.3878, 13.0709] |
| **c** | −69.5756 | \[−71.9530, −67.1982] |

Tajta konfidensintervall vilket indikerar att det är en bra modell. Kollade även residualer och inga problem där.

Plotten:

https://imgur.com/a/knvQ6ZP

Litet data om uppskattad varians:

Frequency (Hz) Squared Error (dB²)
20 0.78
30 2.18 ← largest
63 0.0003
315 0.000035
6300 0.0000014 ← smallest

Kan testköras med denna EEL kod: // Log-polynomial EQ model in dB
// f(freq) = a * ln(freq)^2 + b * ln(freq) + c

// Coefficients from the fit
a = -0.5015;
b = 12.2293;
c = -69.5756;

@slider
slider1: freq (Hz) = 100 < 20, 20000, 1 >;

// Calculate gain in dB
log_f = log(slider1);
gain_db = a * log_f * log_f + b * log_f + c;

// Convert to linear gain
gain = 10^(gain_db / 20);

// Output (for monitoring)
sprintf(#out, "Gain at %.1f Hz = %.2f dB (%.3f linear)", slider1, gain_db, gain);
gfx_drawstr(#out);
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in