ഒരു ആഴമുള്ള ന്യൂറൽ നെറ്റ്വർക്ക് പരിശീലിപ്പിക്കുക എന്നത് അടിസ്ഥാനപരമായി ഒരു കംപ്രഷൻ ടാസ്കാണ്. നമ്മുടെ പരിശീലന ഡാറ്റ വിതരണത്തെ നിരവധി മെട്രിക്സുകൾ കൊണ്ട് പാരാമീറ്ററൈസ് ചെയ്ത ഒരു ഫംഗ്ഷനായി പ്രതിനിധീകരിക്കാൻ ഞങ്ങൾ ആഗ്രഹിക്കുന്നു. വിതരണം കൂടുതൽ സങ്കീർണ്ണമാകുന്തോറും കൂടുതൽ പാരാമീറ്ററുകൾ ആവശ്യമാണ്. മുഴുവൻ വിതരണവും ഏകദേശം കണക്കാക്കുന്നതിന്റെ യുക്തി, അനുമാന സമയത്തിൽ ഏത് സാധുവായ പോയിന്റും അതേ മോഡൽ ഉപയോഗിച്ച്, അതേ ഭാരങ്ങളോടെ മുന്നോട്ട് കൊണ്ടുപോകാൻ കഴിയും എന്നതാണ്. എന്നാൽ നമ്മുടെ മോഡൽ അനുമാന സമയത്ത് തന്നെ, തൽക്ഷണം പരിശീലിപ്പിച്ചാൽ എന്തുണ്ടാകും? അപ്പോൾ, മുന്നോട്ട് കൊണ്ടുപോകുമ്പോൾ, ചുറ്റുമുള്ള പ്രാദേശിക വിതരണം മാത്രമേ മോഡൽ ചെയ്യേണ്ടതുള്ളൂ. പ്രാദേശിക പ്രദേശത്തിന് മുഴുവൻ പരിശീലന സെറ്റിനേക്കാൾ കുറഞ്ഞ ഡൈമെൻഷണാലിറ്റി ഉണ്ടായിരിക്കണം, അതിനാൽ വളരെ ലളിതമായ ഒരു മോഡൽ മതിയാകും!
ഇതാണ് പ്രാദേശിക ഏകദേശനത്തിന്റെയോ പ്രാദേശിക റിഗ്രഷന്റെയോ പിന്നിലുള്ള ആശയം. നമുക്ക് ഒരു ലളിതമായ റിഗ്രഷൻ ടാസ്ക് പരിഗണിക്കാം.
ടാസ്ക്
ഇനിപ്പറയുന്ന ഡാറ്റയുടെ സാമ്പിളുകൾ നമുക്ക് നൽകിയിരിക്കുന്നു:
ഇവിടെ
പ്ലോട്ടിംഗ് കോഡ്
from pathlib import Path
import numpy as np
import plotly.graph_objects as go
# Generate data
np.random.seed(42)
n_points = 100
X = np.random.uniform(0, 1, n_points)
epsilon = np.random.normal(0, 1 / 3, n_points)
Y = np.sin(4 * X) + epsilon
# True function
x_true = np.linspace(0, 1, 500)
y_true = np.sin(4 * x_true)
# Create the plot
fig = go.Figure()
# Add scatter points for noisy data
fig.add_trace(
go.Scatter(
x=X,
y=Y,
mode="markers",
name="Noisy Data",
marker=dict(color="gray"),
)
)
# Add true function
fig.add_trace(
go.Scatter(
x=x_true,
y=y_true,
mode="lines",
name="True Function",
line=dict(color="red"),
)
)
# Update layout shared across themes
fig.update_layout(
title="Data",
xaxis_title="X",
yaxis_title="Y",
)
themes = [
{
"name": "light",
"template": "plotly_white",
"font_color": "#141413",
"background": "#f0efea",
"axis_color": "#141413",
"gridcolor": "rgba(20, 20, 19, 0.2)",
},
{
"name": "dark",
"template": "plotly_dark",
"font_color": "#f0efea",
"background": "#141413",
"axis_color": "#f0efea",
"gridcolor": "rgba(240, 239, 234, 0.2)",
},
]
output_dir = Path(__file__).resolve().parents[3] / "static"
output_dir.mkdir(parents=True, exist_ok=True)
for theme in themes:
themed_fig = go.Figure(fig)
themed_fig.update_layout(
template=theme["template"],
font=dict(color=theme["font_color"]),
paper_bgcolor=theme["background"],
plot_bgcolor=theme["background"],
)
themed_fig.update_xaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
themed_fig.update_yaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
filename = output_dir / f"local_approximation_data_{theme['name']}.html"
themed_fig.write_html(filename)
print(f"Saved plot to {filename}")
# Show the plot
fig.show()
ഡാറ്റാസെറ്റ് എന്ന് സൂചിപ്പിക്കുന്നു, അതിൽ എന്ന സാമ്പിളുകൾ അടങ്ങിയിരിക്കുന്നു.
ഡാറ്റയിലൂടെ ഒരു യുക്തിസഹമായ വക്രം ഫിറ്റ് ചെയ്യുക എന്നതാണ് നമ്മുടെ ടാസ്ക്, അത് യഥാർത്ഥ ഫംഗ്ഷനെ ഏകദേശം പൊരുത്തപ്പെടുത്തുന്നു. ഈ വക്രത്തെ എന്ന് സൂചിപ്പിക്കാം.
കെ അടുത്തുള്ള അയൽക്കാർ
ഏതെങ്കിലും നൽകിയാൽ, ഒരു സമീപനം എന്നത് എന്നതിലേക്ക് അടുത്തുള്ള മൂല്യങ്ങൾ എടുത്ത്, അവയുടെ മൂല്യങ്ങളുടെ ശരാശരി കണക്കാക്കുക എന്നതാണ്. അതായത്,
ഇവിടെ എന്നത് എന്നതിലേക്കുള്ള അടുത്തുള്ള പോയിന്റുകളെ സൂചിപ്പിക്കുന്നു.
പ്ലോട്ടിംഗ് കോഡ്
from pathlib import Path
import numpy as np
import plotly.graph_objects as go
# ഡാറ്റ ജനറേറ്റ് ചെയ്യുക
np.random.seed(42)
n_points = 100
X = np.random.uniform(0, 1, n_points)
epsilon = np.random.normal(0, 1 / 3, n_points)
Y = np.sin(4 * X) + epsilon
# യഥാർത്ഥ ഫംഗ്ഷൻ
x_true = np.linspace(0, 1, 500)
y_true = np.sin(4 * x_true)
# വിവിധ k-യ്ക്കുള്ള k-NN
x_curve = np.arange(0, 1, 0.01)
k_range = range(1, 21)
y_curves_knn = {}
for k in k_range:
y_curve = []
for x in x_curve:
distances = np.square(X - x)
nearest_indices = np.argsort(distances)[:k]
y_curve.append(np.mean(Y[nearest_indices]))
y_curves_knn[k] = y_curve
# Plotly ഫിഗർ സൃഷ്ടിക്കുക
fig = go.Figure()
# സ്റ്റാറ്റിക് ട്രേസുകൾ ചേർക്കുക
fig.add_trace(
go.Scatter(x=X, y=Y, mode="markers", name="Noisy Data", marker=dict(color="gray"))
)
fig.add_trace(
go.Scatter(
x=x_true, y=y_true, mode="lines", name="True Function", line=dict(color="red")
)
)
# ആദ്യത്തെ k-NN വക്രം ചേർക്കുക (k=13, സ്ലൈഡറിന്റെ ഡിഫോൾട്ട് സ്ഥാനം)
initial_k = 13
fig.add_trace(
go.Scatter(
x=x_curve,
y=y_curves_knn[initial_k],
mode="lines",
name="k-NN Curve",
line=dict(color="yellow"),
)
)
# സ്ലൈഡർ സ്റ്റെപ്പുകൾ നിർവചിക്കുക
steps = []
for k in k_range:
step = dict(
method="update",
args=[
{"y": [Y, y_true, y_curves_knn[k]]}, # ട്രേസുകളുടെ y-ഡാറ്റ അപ്ഡേറ്റ് ചെയ്യുക
{
"title": f"Interactive k-NN Curve with Slider for k = {k}"
}, # ടൈറ്റിൽ ഡൈനാമികായി അപ്ഡേറ്റ് ചെയ്യുക
],
label=f"{k}",
)
steps.append(step)
# ലേഔട്ടിലേക്ക് സ്ലൈഡർ ചേർക്കുക
sliders = [
dict(
active=initial_k - 1,
currentvalue={"prefix": "k = "},
pad={"t": 50},
steps=steps,
)
]
fig.update_layout(
sliders=sliders,
title=f"Interactive k-NN Curve with Slider for k = {initial_k}",
xaxis_title="X",
yaxis_title="Y",
)
themes = [
{
"name": "light",
"template": "plotly_white",
"font_color": "#141413",
"background": "#f0efea",
"axis_color": "#141413",
"gridcolor": "rgba(20, 20, 19, 0.2)",
},
{
"name": "dark",
"template": "plotly_dark",
"font_color": "#f0efea",
"background": "#141413",
"axis_color": "#f0efea",
"gridcolor": "rgba(240, 239, 234, 0.2)",
},
]
output_dir = Path(__file__).resolve().parents[3] / "static"
output_dir.mkdir(parents=True, exist_ok=True)
for theme in themes:
themed_fig = go.Figure(fig)
themed_fig.update_layout(
template=theme["template"],
font=dict(color=theme["font_color"]),
paper_bgcolor=theme["background"],
plot_bgcolor=theme["background"],
)
themed_fig.update_xaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
themed_fig.update_yaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
html_path = output_dir / f"knn_slider_{theme['name']}.html"
themed_fig.write_html(html_path)
print(f"Saved interactive plot to {html_path}")
# പ്ലോട്ട് കാണിക്കുക
fig.show()
സ്ലൈഡർ ഉപയോഗിച്ച് നിങ്ങൾക്ക് കാണാൻ കഴിയും, വലിയ മിനുസമാർന്ന ഒരു വക്രത്തിന് കാരണമാകുന്നു, എന്നാൽ ചെറിയ വക്രങ്ങൾ കുറച്ച് ശബ്ദം ഉൾക്കൊള്ളുന്നു. അങ്ങേയറ്റത്തെ സാഹചര്യങ്ങളിൽ, പരിശീലന ഡാറ്റയെ കൃത്യമായി പിന്തുടരുന്നു ഒപ്പം ഒരു പരന്ന ആഗോള ശരാശരി നൽകുന്നു.
നദരായ–വാട്സൺ കെർണൽ റിഗ്രഷൻ
നിങ്ങളുടെ ഡാറ്റയുടെ ഉപഗണം പോയിന്റുകളായി പരിമിതപ്പെടുത്തുന്നതിന് പകരം, സെറ്റിലെ എല്ലാ പോയിന്റുകളും പരിഗണിക്കാം, എന്നാൽ ഓരോ പോയിന്റിന്റെയും സംഭാവന അതിന്റെ എന്നതിലുള്ള സാമീപ്യത്തിന്റെ അടിസ്ഥാനത്തിൽ ഭാരം നൽകാം. മോഡൽ പരിഗണിക്കുക
ഇവിടെ ഒരു കെർണൽ ആണ്, അത് ഞങ്ങൾ ഒരു സാമീപ്യ മെട്രിക് ആയി ഉപയോഗിക്കും.
ഈ ഫംഗ്ഷൻ എന്നത് പാരാമീറ്ററൈസ് ചെയ്യപ്പെട്ടിരിക്കുന്നു, ഇത് ബാൻഡ്വിഡ്ത്ത് എന്നറിയപ്പെടുന്നു, ഇത് ഡാറ്റയിലെ മൂല്യങ്ങളുടെ ഏത് പരിധിയാണ് ന്റെ ഔട്ട്പുട്ടിൽ പങ്കുവഹിക്കുന്നതെന്ന് നിയന്ത്രിക്കുന്നു. ഈ ഫംഗ്ഷനുകൾ പ്ലോട്ട് ചെയ്താൽ ഇത് വ്യക്തമാകും.
കെർണൽ ഫംഗ്ഷനുകൾ
താഴെ പ്ലോട്ട് ചെയ്തിരിക്കുന്നത്
ആണ്. ഇവിടെ എന്നത് യുടെ പിന്തുണയിൽ അതിന്റെ സമാകലനം ആയി നിലനിർത്തുന്നു.
പ്ലോട്ടിംഗ് കോഡ്
from pathlib import Path
import numpy as np
import plotly.graph_objects as go
from scipy.integrate import quad
# കെർണൽ ഫംഗ്ഷനുകൾ നിർവ്വചിക്കുക
def epanechnikov_kernel(u):
return np.maximum(0, 0.75 * (1 - u**2))
def tricube_kernel(u):
return np.maximum(0, (1 - np.abs(u) ** 3) ** 3)
def gaussian_kernel(u):
return np.exp(-0.5 * u**2) / np.sqrt(2 * np.pi)
def renormalized_kernel(kernel_func, u_range, bandwidth):
def kernel_with_lambda(u):
scaled_u = u / bandwidth
normalization_factor, _ = quad(lambda v: kernel_func(v / bandwidth), *u_range)
return kernel_func(scaled_u) / normalization_factor
return kernel_with_lambda
# കെർണൽ ഫംഗ്ഷൻ പ്ലോട്ട് ജനറേറ്റർ
def generate_kernel_plot(
kernel_name, kernel_func, x_range, u_range, lambda_values, y_range
):
fig = go.Figure()
# പ്രാരംഭ ലാംഡ
initial_lambda = lambda_values[len(lambda_values) // 2]
# പ്രാരംഭ കെർണൽ വക്രം സൃഷ്ടിക്കുക
x = np.linspace(*x_range, 500)
kernel_with_lambda = renormalized_kernel(kernel_func, u_range, initial_lambda)
y = kernel_with_lambda(x)
fig.add_trace(
go.Scatter(
x=x,
y=y,
mode="lines",
name=f"{kernel_name} കെർണൽ (λ={initial_lambda:.2f})",
line=dict(color="green"),
)
)
# സ്ലൈഡറിനായി ഫ്രെയിമുകൾ സൃഷ്ടിക്കുക
frames = []
for bandwidth in lambda_values:
kernel_with_lambda = renormalized_kernel(kernel_func, u_range, bandwidth)
y = kernel_with_lambda(x)
frames.append(
go.Frame(
data=[
go.Scatter(
x=x,
y=y,
mode="lines",
name=f"{kernel_name} കെർണൽ (λ={bandwidth:.2f})",
line=dict(color="green"),
)
],
name=f"{bandwidth:.2f}",
)
)
# ഫിഗറിലേക്ക് ഫ്രെയിമുകൾ ചേർക്കുക
fig.frames = frames
# സ്ലൈഡർ ചേർക്കുക
sliders = [
{
"active": len(lambda_values) // 2,
"currentvalue": {"prefix": "ബാൻഡ്വിഡ്ത്ത് λ: "},
"steps": [
{
"args": [
[f"{bandwidth:.2f}"],
{"frame": {"duration": 0, "redraw": True}, "mode": "immediate"},
],
"label": f"{bandwidth:.2f}",
"method": "animate",
}
for bandwidth in lambda_values
],
}
]
# ലേഔട്ട് അപ്ഡേറ്റ് ചെയ്യുക
fig.update_layout(
title=f"{kernel_name} കെർണൽ ഫംഗ്ഷൻ",
xaxis_title="u",
yaxis_title="K(u)",
yaxis_range=y_range,
sliders=sliders,
autosize=True,
updatemenus=[
{
"buttons": [
# {
# "args": [
# None,
# {
# "frame": {"duration": 500, "redraw": True},
# "fromcurrent": True,
# },
# ],
# "label": "പ്ലേ",
# "method": "animate",
# },
# {
# "args": [
# [None],
# {
# "frame": {"duration": 0, "redraw": True},
# "mode": "immediate",
# },
# ],
# "label": "നിർത്തുക",
# "method": "animate",
# },
],
"direction": "left",
"pad": {"r": 10, "t": 87},
"showactive": False,
"type": "buttons",
"x": 0.1,
"xanchor": "right",
"y": 0,
"yanchor": "top",
}
],
)
return fig
# കെർണൽ ഫംഗ്ഷനുകൾ
kernels = {
"Epanechnikov": epanechnikov_kernel,
"Tricube": tricube_kernel,
"Gaussian": gaussian_kernel,
}
# പാരാമീറ്ററുകൾ
x_range_plot = (-3, 3) # പ്ലോട്ടിനുള്ള u മൂല്യങ്ങളുടെ പരിധി
u_range_integration = (-3, 3) # സാധാരണീകരണത്തിനുള്ള പരിധി
lambda_values = np.linspace(0.01, 2, 20) # 0.01 മുതൽ 2 വരെയുള്ള രേഖീയ λ മൂല്യങ്ങൾ
y_range_plot = (0, 1.5) # സാധാരണീകരിച്ച ഫംഗ്ഷനുകൾക്ക് അനുയോജ്യമാക്കിയ പരിധി
# ഓരോ കെർണലിനും പ്ലോട്ടുകൾ സൃഷ്ടിച്ച് പ്രദർശിപ്പിക്കുക
themes = [
{
"name": "light",
"template": "plotly_white",
"font_color": "#141413",
"background": "#f0efea",
"axis_color": "#141413",
"gridcolor": "rgba(20, 20, 19, 0.2)",
},
{
"name": "dark",
"template": "plotly_dark",
"font_color": "#f0efea",
"background": "#141413",
"axis_color": "#f0efea",
"gridcolor": "rgba(240, 239, 234, 0.2)",
},
]
output_dir = Path(__file__).resolve().parents[3] / "static"
output_dir.mkdir(parents=True, exist_ok=True)
for kernel_name, kernel_func in kernels.items():
fig = generate_kernel_plot(
kernel_name,
kernel_func,
x_range_plot,
u_range_integration,
lambda_values,
y_range_plot,
)
# തീം ചെയ്ത ഫിഗറുകൾ HTML ഫയലുകളായി സംരക്ഷിക്കുക
for theme in themes:
themed_fig = go.Figure(fig)
themed_fig.update_layout(
template=theme["template"],
font=dict(color=theme["font_color"]),
paper_bgcolor=theme["background"],
plot_bgcolor=theme["background"],
)
themed_fig.update_xaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
themed_fig.update_yaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
filename = (
output_dir
/ f"{kernel_name}_dynamic_normalization_kernel_function_{theme['name']}.html"
)
themed_fig.write_html(filename, auto_play=False)
print(f"Saved {kernel_name} kernel plot to {filename}")
# ഫിഗർ പ്രദർശിപ്പിക്കുക
fig.show()
ഫലങ്ങൾ
ഇപ്പോൾ ഓരോ കെർണൽ ഫങ്ഷനുകൾക്കുമുള്ള ഫലങ്ങൾ ഞങ്ങൾ പ്ലോട്ട് ചെയ്യുന്നു. ഓരോ പ്ലോട്ടിലും ഒരു സ്ലൈഡർ ഉണ്ട്, അത് ഔട്ട്പുട്ട് തത്സമയം നിയന്ത്രിക്കുന്നു.
പ്ലോട്ടിംഗ് കോഡ്
from pathlib import Path
import numpy as np
import plotly.graph_objects as go
# കെർണൽ ഫങ്ഷനുകൾ നിർവ്വചിക്കുക
def epanechnikov_kernel(u):
return np.maximum(0, 0.75 * (1 - u**2))
def tricube_kernel(u):
return np.maximum(0, (1 - np.abs(u) ** 3) ** 3)
def gaussian_kernel(u):
return np.exp(-0.5 * u**2) / np.sqrt(2 * np.pi)
# കെർണൽ റിഗ്രഷൻ ഫങ്ഷൻ
def kernel_regression(X, Y, x_curve, kernel_func, bandwidth):
y_curve = []
for x in x_curve:
distances = np.abs(X - x) / bandwidth
weights = kernel_func(distances)
weighted_average = (
np.sum(weights * Y) / np.sum(weights) if np.sum(weights) > 0 else 0
)
y_curve.append(weighted_average)
return y_curve
# ഡാറ്റ ജനറേറ്റ് ചെയ്യുക
np.random.seed(42)
n_points = 100
X = np.random.uniform(0, 1, n_points)
epsilon = np.random.normal(0, 1 / 3, n_points)
Y = np.sin(4 * X) + epsilon
# യഥാർത്ഥ വക്രം
x_true = np.linspace(0, 1, 500)
y_true = np.sin(4 * x_true)
# കെർണൽ എസ്റ്റിമേഷനുള്ള പോയിന്റുകൾ
x_curve = x_true
# കെർണൽ ഫങ്ഷനുകൾ
kernels = {
"Epanechnikov": epanechnikov_kernel,
"Tricube": tricube_kernel,
"Gaussian": gaussian_kernel,
}
# സ്ലൈഡറിനുള്ള ബാൻഡ്വിഡ്ത്ത് പരിധി ലോഗ് സ്പേസിൽ
lambda_values = np.logspace(-2, 0, 20) # 0.01 മുതൽ 1 വരെ
# ഓരോ കെർണലിനും വെവ്വേറെ പ്ലോട്ടുകൾ ജനറേറ്റ് ചെയ്യുക
themes = [
{
"name": "light",
"template": "plotly_white",
"font_color": "#141413",
"background": "#f0efea",
"axis_color": "#141413",
"gridcolor": "rgba(20, 20, 19, 0.2)",
},
{
"name": "dark",
"template": "plotly_dark",
"font_color": "#f0efea",
"background": "#141413",
"axis_color": "#f0efea",
"gridcolor": "rgba(240, 239, 234, 0.2)",
},
]
output_dir = Path(__file__).resolve().parents[3] / "static"
output_dir.mkdir(parents=True, exist_ok=True)
# ഓരോ കെർണലിനും വെവ്വേറെ പ്ലോട്ടുകൾ ജനറേറ്റ് ചെയ്യുക
for kernel_name, kernel_func in kernels.items():
fig = go.Figure()
# ശബ്ദമുള്ള ഡാറ്റയ്ക്കായി സ്കാറ്റർ പോയിന്റുകൾ ചേർക്കുക
fig.add_trace(
go.Scatter(
x=X, y=Y, mode="markers", name="Noisy Data", marker=dict(color="gray")
)
)
# യഥാർത്ഥ ഫങ്ഷൻ ചേർക്കുക
fig.add_trace(
go.Scatter(
x=x_true,
y=y_true,
mode="lines",
name="True Function",
line=dict(color="red"),
)
)
# പ്രാരംഭ കെർണൽ വക്രം ചേർക്കുക
initial_bandwidth = lambda_values[0]
y_curve = kernel_regression(X, Y, x_curve, kernel_func, initial_bandwidth)
fig.add_trace(
go.Scatter(
x=x_curve,
y=y_curve,
mode="lines",
name=f"Nadaraya-Watson ({kernel_name})",
line=dict(color="green"),
)
)
# സ്ലൈഡറിനായി ഫ്രെയിമുകൾ സൃഷ്ടിക്കുക
frames = []
for bandwidth in lambda_values:
y_curve = kernel_regression(X, Y, x_curve, kernel_func, bandwidth)
frames.append(
go.Frame(
data=[
go.Scatter(
x=X,
y=Y,
mode="markers",
name="Noisy Data",
marker=dict(color="gray"),
),
go.Scatter(
x=x_true,
y=y_true,
mode="lines",
name="True Function",
line=dict(color="red"),
),
go.Scatter(
x=x_curve,
y=y_curve,
mode="lines",
name=f"Nadaraya-Watson ({kernel_name})",
line=dict(color="green"),
),
],
name=f"{bandwidth:.2f}",
)
)
# ഫ്രെയിമുകൾ ഫിഗറിലേക്ക് ചേർക്കുക
fig.frames = frames
# സ്ലൈഡർ ചേർക്കുക
sliders = [
{
"active": 0,
"currentvalue": {"prefix": "Bandwidth λ: "},
"steps": [
{
"args": [
[f"{bandwidth:.2f}"],
{"frame": {"duration": 0, "redraw": True}, "mode": "immediate"},
],
"label": f"{bandwidth:.2f}",
"method": "animate",
}
for bandwidth in lambda_values
],
}
]
# ലേഔട്ട് അപ്ഡേറ്റ് ചെയ്യുക
fig.update_layout(
autosize=True,
title=f"Nadaraya-Watson Kernel Regression ({kernel_name} Kernel)",
xaxis_title="X",
yaxis_title="Y",
sliders=sliders,
updatemenus=[
{
"buttons": [
{
"args": [
None,
{
"frame": {"duration": 500, "redraw": True},
"fromcurrent": True,
},
],
"label": "Play",
"method": "animate",
},
{
"args": [
[None],
{
"frame": {"duration": 0, "redraw": True},
"mode": "immediate",
},
],
"label": "Pause",
"method": "animate",
},
],
"direction": "left",
"pad": {"r": 10, "t": 87},
"showactive": False,
"type": "buttons",
"x": 0.1,
"xanchor": "right",
"y": 0,
"yanchor": "top",
}
],
)
# ഓരോ തീംയ്ക്കും ഫിഗർ ഒരു HTML ഫയലിലേക്ക് സേവ് ചെയ്യുക
for theme in themes:
themed_fig = go.Figure(fig)
themed_fig.update_layout(
template=theme["template"],
font=dict(color=theme["font_color"]),
paper_bgcolor=theme["background"],
plot_bgcolor=theme["background"],
)
themed_fig.update_xaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
themed_fig.update_yaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
filename = output_dir / f"{kernel_name}_kernel_regression_{theme['name']}.html"
themed_fig.write_html(filename, auto_play=False)
print(f"Saved {kernel_name} kernel plot to {filename}")
# ഫിഗർ കാണിക്കുക
fig.show()
ഡാറ്റയുടെ ഒരു ലളിതമായ തൂക്കമുള്ള ശരാശരി ഒരു സൈനുസോയിഡ് നന്നായി മോഡൽ ചെയ്യാൻ കഴിയുന്നതായി നമുക്ക് കാണാം.
ലോക്കൽ ലീനിയർ റിഗ്രഷൻ
നദരായ-വാട്സൺ കെർണൽ റിഗ്രഷനിൽ, എന്ന കെർണൽ ഫംഗ്ഷൻ നിർവചിക്കുന്ന ഒരു പരിസരത്തിൽ നമ്മൾ ഒരു ഭാരമുള്ള ശരാശരി എടുക്കുന്നു. ഇതിൽ ഒരു സാധ്യമായ പ്രശ്നം ലോക്കൽ പരിസരങ്ങളിലെ മിനുസമാർന്ന ഇന്റർപോളേഷൻ ആണ്, കാരണം ആ പ്രദേശം യാതൊരു മോഡലും പാലിക്കുന്നുവെന്ന് നമ്മൾ യഥാർത്ഥത്തിൽ അനുമാനിക്കുന്നില്ല.
ഓരോ പ്രദേശവും ലോക്കലായി രേഖീയമാണെന്ന് നമ്മൾ അനുമാനിച്ചാൽ എന്തുണ്ടാകും? അപ്പോൾ, നമുക്ക് ലീസ്റ്റ് സ്ക്വയർസ് ഫിറ്റിനായി പരിഹരിക്കാനും സ്വതന്ത്രമായി ഇന്റർപോളേറ്റ് ചെയ്യാനും കഴിയും!
പ്രദേശം: $k$-NN
നമുക്ക് നമ്മുടെ ലോക്കൽ പ്രദേശം നമ്മുടെ ഇൻപുട്ടിന്റെ അടുത്തുള്ള അയൽക്കാരായി നിർവചിക്കാം. എന്നും അതിനനുസരിച്ചുള്ള മൂല്യങ്ങളായും എടുക്കാം. ലീസ്റ്റ് സ്ക്വയർസ് ഫിറ്റ് കോഫിഫിഷ്യന്റുകൾ
പ്ലോട്ടിംഗ് കോഡ്
from pathlib import Path
import numpy as np
import plotly.graph_objects as go
# ഡാറ്റ ജനറേറ്റ് ചെയ്യുക
np.random.seed(42)
n_points = 100
X = np.random.uniform(0, 1, n_points)
epsilon = np.random.normal(0, 1 / 3, n_points)
Y = np.sin(4 * X) + epsilon
# യഥാർത്ഥ ഫംഗ്ഷൻ
x_true = np.linspace(0, 1, 500)
y_true = np.sin(4 * x_true)
# k-NN ലോക്കൽ ലീനിയർ റിഗ്രഷൻ
def knn_linear_regression(X, Y, x_curve, k_range):
y_curves = {}
for k in k_range:
y_curve = []
for x in x_curve:
# k അടുത്തുള്ള അയൽക്കാരെ കണ്ടെത്തുക
distances = np.abs(X - x)
nearest_indices = np.argsort(distances)[:k]
# k അടുത്തുള്ള അയൽക്കാരെ തിരഞ്ഞെടുക്കുക
X_knn = X[nearest_indices]
Y_knn = Y[nearest_indices]
# k-നെയറസ്റ്റ് നീബർമാരുടെ ഡിസൈൻ മാട്രിക്സ് സൃഷ്ടിക്കുക
X_design = np.vstack((np.ones_like(X_knn), X_knn)).T
# ഓർഡിനറി ലീസ്റ്റ് സ്ക്വയർസ് ഉപയോഗിച്ച് ബീറ്റയ്ക്കായി പരിഹരിക്കുക
beta = np.linalg.pinv(X_design.T @ X_design) @ X_design.T @ Y_knn
# y-മൂല്യം പ്രവചിക്കുക
y_curve.append(beta[0] + beta[1] * x)
y_curves[k] = y_curve
return y_curves
# പൊതു വേരിയബിളുകൾ
x_curve = np.arange(0, 1, 0.01)
k_range = range(1, 21) # k യുടെ മൂല്യങ്ങൾ 1 മുതൽ 20 വരെ
initial_k = 10 # k യുടെ ഡിഫോൾട്ട് മൂല്യം
# k-NN ഉപയോഗിച്ച് LLR കണക്കാക്കുക
y_curves_knn = knn_linear_regression(X, Y, x_curve, k_range)
# Plotly ഫിഗർ സൃഷ്ടിക്കുക
fig = go.Figure()
# സ്റ്റാറ്റിക് ട്രേസുകൾ ചേർക്കുക
fig.add_trace(
go.Scatter(x=X, y=Y, mode="markers", name="Noisy Data", marker=dict(color="gray"))
)
fig.add_trace(
go.Scatter(
x=x_true, y=y_true, mode="lines", name="True Function", line=dict(color="red")
)
)
# ആദ്യത്തെ k-NN കർവ് (k=initial_k) ചേർക്കുക
fig.add_trace(
go.Scatter(
x=x_curve,
y=y_curves_knn[initial_k],
mode="lines",
name="k-NN Curve",
line=dict(color="yellow"),
)
)
# സ്ലൈഡർ സ്റ്റെപ്പുകൾ നിർവചിക്കുക
steps = []
for k in k_range:
step = dict(
method="update",
args=[
{"y": [Y, y_true, y_curves_knn[k]]}, # ട്രേസുകൾക്കായി y-ഡാറ്റ അപ്ഡേറ്റ് ചെയ്യുക
{
"title": f"k-NN Local Linear Regression Curve with k = {k}"
}, # ടൈറ്റിൽ ഡൈനാമികായി അപ്ഡേറ്റ് ചെയ്യുക
],
label=f"{k}",
)
steps.append(step)
# ലേഔട്ടിലേക്ക് സ്ലൈഡർ ചേർക്കുക
sliders = [
dict(
active=k_range.index(initial_k), # initial_k യുടെ ഇൻഡെക്സ് ഉപയോഗിക്കുക
currentvalue={"prefix": "k = "},
pad={"t": 50},
steps=steps,
)
]
fig.update_layout(
autosize=True,
sliders=sliders,
title=f"k-NN Local Linear Regression Curve with k = {initial_k}",
xaxis_title="X",
yaxis_title="Y",
)
themes = [
{
"name": "light",
"template": "plotly_white",
"font_color": "#141413",
"background": "#f0efea",
"axis_color": "#141413",
"gridcolor": "rgba(20, 20, 19, 0.2)",
},
{
"name": "dark",
"template": "plotly_dark",
"font_color": "#f0efea",
"background": "#141413",
"axis_color": "#f0efea",
"gridcolor": "rgba(240, 239, 234, 0.2)",
},
]
output_dir = Path(__file__).resolve().parents[3] / "static"
output_dir.mkdir(parents=True, exist_ok=True)
for theme in themes:
themed_fig = go.Figure(fig)
themed_fig.update_layout(
template=theme["template"],
font=dict(color=theme["font_color"]),
paper_bgcolor=theme["background"],
plot_bgcolor=theme["background"],
)
themed_fig.update_xaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
themed_fig.update_yaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
html_path = output_dir / f"knn_slider_llr_{theme['name']}.html"
themed_fig.write_html(html_path)
print(f"Saved interactive k-NN plot to {html_path}")
# പ്ലോട്ട് കാണിക്കുക
fig.show()
ചെറിയ മൂല്യങ്ങൾക്ക് ഔട്ട്പുട്ട് വളരെ പരുക്കനായിരിക്കുമെന്ന് നമുക്ക് കാണാം.
പ്രദേശം: കെർണൽ ഫംഗ്ഷൻ
നദരായ-വാട്സൺ കെർണലിൽ നിന്നുള്ള ചില ആശയങ്ങൾ നമുക്ക് പുനരുപയോഗിക്കാം. പരിശീലന സെറ്റിലെ എല്ലാ പോയിന്റുകളും വ്യത്യസ്ത അളവിൽ പരിഗണിക്കാൻ ഞങ്ങൾ ആഗ്രഹിക്കുന്നു, ലോക്കൽ പ്രദേശത്തിനുള്ളിൽ കൂടുതൽ ഭാരവും പുറത്ത് കുറഞ്ഞ ഭാരവും നൽകുന്നു.
ഇതിനായി, ഭാരമുള്ള ലീസ്റ്റ് സ്ക്വയേഴ്സ് ലക്ഷ്യം ഉപയോഗിക്കാം, ഭാരങ്ങൾ ആയി. ഇതിന് പരിഹാരമുണ്ട്
വിവിധ കെർണൽ ഫംഗ്ഷനുകൾ -നുള്ള ഫലങ്ങൾ പ്ലോട്ട് ചെയ്യുന്നു:
പ്ലോട്ടിംഗ് കോഡ്
from pathlib import Path
import numpy as np
import plotly.graph_objects as go
# ഡാറ്റ ജനറേറ്റ് ചെയ്യുക
np.random.seed(42)
n_points = 100
X = np.random.uniform(0, 1, n_points)
epsilon = np.random.normal(0, 1 / 3, n_points)
Y = np.sin(4 * X) + epsilon
# യഥാർത്ഥ ഫംഗ്ഷൻ
x_true = np.linspace(0, 1, 500)
y_true = np.sin(4 * x_true)
# കെർണലുകൾ
def gaussian_kernel(u):
return np.exp(-0.5 * u**2)
def epanechnikov_kernel(u):
return np.maximum(0, 1 - u**2)
def tricube_kernel(u):
return np.maximum(0, (1 - np.abs(u) ** 3) ** 3)
# ഒരു പ്രത്യേക കെർണലിനുള്ള ലോക്കൽ ലീനിയർ റിഗ്രഷൻ
def local_linear_regression(X, Y, x_curve, bandwidths, kernel):
y_curves = {}
for λ in bandwidths:
λ_rounded = round(λ, 2)
y_curve = []
for x in x_curve:
# നിർദ്ദിഷ്ട കെർണൽ ഉപയോഗിച്ച് ഭാരങ്ങൾ കണക്കാക്കുക
distances = (X - x) / λ
weights = kernel(distances)
W = np.diag(weights)
# ഡിസൈൻ മാട്രിക്സ് സൃഷ്ടിക്കുക
X_design = np.vstack((np.ones_like(X), X)).T
# ഭാരമുള്ള ലീസ്റ്റ് സ്ക്വയേഴ്സ് ഉപയോഗിച്ച് ബീറ്റയ്ക്കായി പരിഹരിക്കുക
beta = np.linalg.pinv(X_design.T @ W @ X_design) @ X_design.T @ W @ Y
# y-മൂല്യം പ്രവചിക്കുക
y_curve.append(beta[0] + beta[1] * x)
y_curves[λ_rounded] = y_curve
return y_curves
# പൊതു വേരിയബിളുകൾ
x_curve = np.arange(0, 1, 0.01)
bandwidths = np.linspace(0.05, 0.5, 20)
initial_λ = bandwidths[len(bandwidths) // 2]
# ഓരോ കെർണലിനും പ്ലോട്ടുകൾ ജനറേറ്റ് ചെയ്യുക
kernels = {
"ഗാസിയൻ കെർണൽ": gaussian_kernel,
"എപനെച്നിക്കോവ് കെർണൽ": epanechnikov_kernel,
"ട്രൈക്യൂബ് കെർണൽ": tricube_kernel,
}
plots = []
for kernel_name, kernel_func in kernels.items():
# നിർദ്ദിഷ്ട കെർണൽ ഉപയോഗിച്ച് LLR കണക്കാക്കുക
y_curves = local_linear_regression(X, Y, x_curve, bandwidths, kernel_func)
# Plotly ഫിഗർ സൃഷ്ടിക്കുക
fig = go.Figure()
# സ്റ്റാറ്റിക് ട്രേസുകൾ ചേർക്കുക
fig.add_trace(
go.Scatter(
x=X, y=Y, mode="markers", name="ശബ്ദമുള്ള ഡാറ്റ", marker=dict(color="gray")
)
)
fig.add_trace(
go.Scatter(
x=x_true,
y=y_true,
mode="lines",
name="യഥാർത്ഥ ഫംഗ്ഷൻ",
line=dict(color="red"),
)
)
# ആദ്യത്തെ LLR വക്രം ചേർക്കുക (ബാൻഡ്വിഡ്ത്തുകളുടെ മധ്യ മൂല്യം ഉപയോഗിച്ച്)
fig.add_trace(
go.Scatter(
x=x_curve,
y=y_curves[round(initial_λ, 2)],
mode="lines",
name=f"{kernel_name} വക്രം",
line=dict(color="yellow"),
)
)
# സ്ലൈഡർ ഘട്ടങ്ങൾ നിർവചിക്കുക
steps = []
for λ in bandwidths:
λ_rounded = round(λ, 2)
step = dict(
method="update",
args=[
{"y": [Y, y_true, y_curves[λ_rounded]]}, # ട്രേസുകൾക്കായി y-ഡാറ്റ അപ്ഡേറ്റ് ചെയ്യുക
{
"title": f"LLR: {kernel_name} ബാൻഡ്വിഡ്ത്ത് λ = {λ_rounded}"
}, # ശീർഷകം ഡൈനാമികായി അപ്ഡേറ്റ് ചെയ്യുക
],
label=f"{λ_rounded}",
)
steps.append(step)
# ലേഔട്ടിലേക്ക് സ്ലൈഡർ ചേർക്കുക
sliders = [
dict(
active=len(bandwidths) // 2, # മധ്യ ബാൻഡ്വിഡ്ത്തിന്റെ ഇൻഡെക്സ് ഉപയോഗിക്കുക
currentvalue={"prefix": "λ = "},
pad={"t": 50},
steps=steps,
)
]
fig.update_layout(
autosize=True,
sliders=sliders,
title=f"LLR: {kernel_name} ബാൻഡ്വിഡ്ത്ത് λ = {round(initial_λ, 2)}",
xaxis_title="X",
yaxis_title="Y",
)
plots.append(fig)
# തീം ചെയ്ത പശ്ചാത്തലങ്ങളുള്ള പ്ലോട്ടുകൾ കാണിക്കുകയും സംരക്ഷിക്കുകയും ചെയ്യുക
themes = [
{
"name": "light",
"template": "plotly_white",
"font_color": "#141413",
"background": "#f0efea",
"axis_color": "#141413",
"gridcolor": "rgba(20, 20, 19, 0.2)",
},
{
"name": "dark",
"template": "plotly_dark",
"font_color": "#f0efea",
"background": "#141413",
"axis_color": "#f0efea",
"gridcolor": "rgba(240, 239, 234, 0.2)",
},
]
output_dir = Path(__file__).resolve().parents[3] / "static"
output_dir.mkdir(parents=True, exist_ok=True)
for kernel_name, fig in zip(kernels.keys(), plots):
fig.show()
for theme in themes:
themed_fig = go.Figure(fig)
themed_fig.update_layout(
template=theme["template"],
font=dict(color=theme["font_color"]),
paper_bgcolor=theme["background"],
plot_bgcolor=theme["background"],
)
themed_fig.update_xaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
themed_fig.update_yaxes(
showline=True,
linecolor=theme["axis_color"],
tickcolor=theme["axis_color"],
tickfont=dict(color=theme["axis_color"]),
title_font=dict(color=theme["axis_color"]),
gridcolor=theme["gridcolor"],
zeroline=False,
)
filename = (
output_dir
/ f"llr_{kernel_name.lower().replace(' ', '_')}_{theme['name']}.html"
)
themed_fig.write_html(filename)
print(f"Saved interactive plot for {kernel_name} to {filename}")
ഫലങ്ങൾ വളരെ മിനുസമാർന്നതായി തോന്നുന്നു!
അവലംബങ്ങൾ
- The Elements of Statistical Learning - ഹാസ്റ്റി, ടിബ്ഷിറാനി, ഫ്രീഡ്മാൻ (2009). ഡാറ്റാ മൈനിംഗ്, അനുമാനം, പ്രവചനം എന്നിവയുടെ സമഗ്രമായ ഒരു മാർഗ്ഗദർശിനി. കൂടുതൽ വായിക്കുക.