Bigger network (128→64→32) and percentile-based training target
- 3 hidden layers instead of 2 for better feature interaction learning - Target is within-band distance percentile (0-1) instead of raw normalized distance — reduces noise from operator/equipment variation
This commit is contained in:
parent
10cbbf47b3
commit
08e4b9abdd
3 changed files with 32 additions and 12 deletions
|
|
@ -52,10 +52,12 @@ defmodule Microwaveprop.Propagation.Model do
|
|||
def build do
|
||||
"features"
|
||||
|> Axon.input(shape: {nil, @feature_count})
|
||||
|> Axon.dense(64, activation: :relu, name: "hidden_1")
|
||||
|> Axon.dense(128, activation: :relu, name: "hidden_1")
|
||||
|> Axon.dropout(rate: 0.2, name: "dropout_1")
|
||||
|> Axon.dense(32, activation: :relu, name: "hidden_2")
|
||||
|> Axon.dropout(rate: 0.1, name: "dropout_2")
|
||||
|> Axon.dense(64, activation: :relu, name: "hidden_2")
|
||||
|> Axon.dropout(rate: 0.15, name: "dropout_2")
|
||||
|> Axon.dense(32, activation: :relu, name: "hidden_3")
|
||||
|> Axon.dropout(rate: 0.1, name: "dropout_3")
|
||||
|> Axon.dense(1, activation: :sigmoid, name: "output")
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -116,13 +116,13 @@ defmodule Mix.Tasks.PropagationTrain do
|
|||
# Evaluate on validation set
|
||||
val_metrics = Model.evaluate(trained_state, val_features, val_targets)
|
||||
IO.puts("Validation metrics:")
|
||||
IO.puts(" RMSE: #{Float.round(val_metrics.rmse, 4)}")
|
||||
IO.puts(" RMSE: #{Float.round(val_metrics.rmse * 100, 2)} points (on 0-100 scale)")
|
||||
IO.puts(" R-squared: #{Float.round(val_metrics.r_squared, 4)}\n")
|
||||
|
||||
# Evaluate on test set
|
||||
test_metrics = Model.evaluate(trained_state, test_features, test_targets)
|
||||
IO.puts("Test metrics:")
|
||||
IO.puts(" RMSE: #{Float.round(test_metrics.rmse, 4)}")
|
||||
IO.puts(" RMSE: #{Float.round(test_metrics.rmse * 100, 2)} points (on 0-100 scale)")
|
||||
IO.puts(" R-squared: #{Float.round(test_metrics.r_squared, 4)}\n")
|
||||
|
||||
# Save model
|
||||
|
|
@ -178,10 +178,31 @@ defmodule Mix.Tasks.PropagationTrain do
|
|||
|
||||
band_counts = Enum.frequencies_by(rows, fn row -> Enum.at(row, 0) end)
|
||||
|
||||
{feature_rows, target_rows} =
|
||||
# Group by band and compute within-band distance percentile as target.
|
||||
# This converts raw distance to "how good were conditions relative to
|
||||
# what's possible on this band" — reduces noise from operator/equipment.
|
||||
rows_by_band =
|
||||
rows
|
||||
|> Enum.filter(fn [band_mhz | _] -> Map.has_key?(@band_max_km, band_mhz) end)
|
||||
|> Enum.map(fn [band_mhz, distance_km, utc_hour, month, lon, temp, dewpoint, pressure, grad, hpbl, pwat] ->
|
||||
|> Enum.group_by(fn [band_mhz | _] -> band_mhz end)
|
||||
|
||||
percentile_lookup =
|
||||
Enum.flat_map(rows_by_band, fn {_band, band_rows} ->
|
||||
distances = band_rows |> Enum.map(fn [_, d | _] -> d end) |> Enum.sort()
|
||||
n = length(distances)
|
||||
|
||||
Enum.map(band_rows, fn [_, distance_km | _] = row ->
|
||||
# Rank this distance within its band (0.0 to 1.0)
|
||||
rank = Enum.count(distances, &(&1 <= distance_km))
|
||||
pct = rank / n
|
||||
{row, pct}
|
||||
end)
|
||||
end)
|
||||
|
||||
{feature_rows, target_rows} =
|
||||
percentile_lookup
|
||||
|> Enum.map(fn {[band_mhz, _distance_km, utc_hour, month, lon, temp, dewpoint, pressure, grad, hpbl, pwat],
|
||||
percentile} ->
|
||||
features =
|
||||
Model.encode_features(%{
|
||||
surface_temp_c: to_float(temp),
|
||||
|
|
@ -196,11 +217,7 @@ defmodule Mix.Tasks.PropagationTrain do
|
|||
freq_mhz: band_mhz
|
||||
})
|
||||
|
||||
# Normalize distance by band's p99 range, cap at 1.0
|
||||
max_km = Map.fetch!(@band_max_km, band_mhz)
|
||||
target = [min(distance_km / max_km, 1.0)]
|
||||
|
||||
{features, target}
|
||||
{features, [percentile]}
|
||||
end)
|
||||
|> Enum.unzip()
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ defmodule Microwaveprop.Propagation.ModelTest do
|
|||
assert %Axon.ModelState{} = params
|
||||
assert Map.has_key?(params.data, "hidden_1")
|
||||
assert Map.has_key?(params.data, "hidden_2")
|
||||
assert Map.has_key?(params.data, "hidden_3")
|
||||
assert Map.has_key?(params.data, "output")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue