Perceptrón je najjednoduchšia umelá neurónová sieť, ktorú navrhol v roku 1957 americký psychológ
Frank Rosenblatt.
Jedná sa o
jednovrstvovú neurónovú sieť, kde jedna vrstva pozostáva z n-vstupov (x_1, x_2,...,x_n) a druhá vrstva z jedného výstupu (y). Výstup je spojený s každým vstupom a pomyselne je takéto spojenie známe z grafových štruktúr z matematiky, kde každé spojenie môže podliehať tzv.
váhovému označeniu, ktoré predstavuje váhovú hodnotu (w_1, w_2,...,w_n). Schematické znázorenie na obrázku nižšie reprezentuje jednoduchý perceptrón, pričom jednotlivé spojenia znázornené úsečkami (v našom prípade predstavujúce jednotlivé váhové prepojenia) sú aplikovateľné aj v iných vedných a technických disciplínach, napr. elektrotechnike, kde takéto prepojenia ilustrujú signály vo vodičoch a podobne.
Signál prenášaný vstupnými neurónmi je buď
binárny (0, 1) alebo
bipolárny (-1, 0 | 1). Výstup z perceptrónu je potom jednoduchá funkcia: y=f(y_in), pričom funkcia sa nazýva aktivačná funkcia, ktorá môže mať rôzne tvary (akákoľvek diferencovateľná funkcia, najčastejšie
sigmoidálna (logistická) funkcia).
Aktivačná funkcia je v zásade určitá brána, alebo hranica, kde dochádza k nejakej zmene, v našom prípade k
zmene váhových hodnôt. Samotné váhové hodnoty sa menia v čase, teda neurónová sieť sa týmto procesom adaptuje a "učí". Za naučenú neurónovú sieť je možné považovať také hodnoty váhových prepojení, kedy nám neurónová sieť poskytuje požadovaný výstup.Zmeny váhových stavov sa realizujú v čase, postupne, podľa určitého algoritmu. Pre perceptrón existuje tzv.
perceptrónový algoritmus.
Výsledná aplikácia perceptrónu, ktorá separuje dve dátové množiny vyzerá nasledovne:
Jedná sa o aplikáciu naprogramovanú v jazyku .NET C#, typu WinForms. V nasledujúcej časti budú popísané niektoré dôležité časti programu.
Hlavná časť programu pozostáva z výpočtu váhových prepojení, tzn.
výpočet trénovacej množniny:
double output;
for (int i = 0; i < num_weights; i++)
{
weights[i] = 0.0;
}
while (stop)
{
stop = false;
for (int i = 0; i < train_exp.Count; i++)
{
output = result(i);
if (train_exp[i] != (int)output)
{
weights[0] += ro * train_exp[i] * train_x[i];
weights[1] += ro * train_exp[i] * train_y[i];
weights[2] += ro * train_exp[i];
stop = false;
}
}
}
lblW1.Text = "w1 = " + weights[0];
lblW2.Text = "w2 = " + weights[1];
lblW0.Text = "w0 = " + weights[2];
Funkcia
Result():
double result(int set)
{
double res;
res = ((train_x[set] * weights[0]) + (train_y[set] * weights[1]) + (1.0 * weights[2]));
if (res > 0.0)
{
res = 1.0;
}
else
{
res = -1.0;
}
return res;
}
Pri definovaní jednotlivých bodov, červenej a zelenej množiny sa vykreslí separačná priamka:
Pen p = new Pen(Color.Blue, 3);
p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
btnTrain.Enabled = false;
float y1 = -((float)weights[0] / (float)weights[1]) * (-200) - ((float)weights[2] / (float)weights[1]);
float y2 = -((float)weights[0] / (float)weights[1]) * (200) - ((float)weights[2] / (float)weights[1]);
if (y1 < 0 && y2 < 0)
{
g.DrawLine(p, 0, 200 + Math.Abs(y1), 400, 200 + Math.Abs(y2));
}
if (y1 < 0 && y2 > 0)
{
g.DrawLine(p, 0, 200 + Math.Abs(y1), 400, 200 - y2);
}
if (y1 > 0 && y2 < 0)
{
g.DrawLine(p, 0, 200 - y1, 400, 200 + Math.Abs(y2));
}
if (y1 > 0 && y2 > 0)
{
g.DrawLine(p, 0, 200 - y1, 400, 200 - y2);
}
this.Controls.Add(pctBox);
pctBox.Image = bmp;
Na záver časť programu, ktorá slúži na interakciu kresliacej plochy a definovanie jednotlivých množín:
//Red class
if (rbtnRed.Checked == true)
{
if (e.X >= 0 && e.X <= 200)
{
//I.kvadrant
if (e.Y >= 0 && e.Y <= 200)
{
train_x.Add(e.X - 200);
train_y.Add(200 - e.Y);
train_exp.Add(1);
g.DrawEllipse(new Pen(Color.Red, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
//III.kvadrant
if (e.Y >= 200 && e.Y <= 400)
{
train_x.Add(e.X - 200);
train_y.Add(e.Y - 200);
train_exp.Add(1);
g.DrawEllipse(new Pen(Color.Red, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
}
if (e.X >= 200 && e.X <= 400)
{
//II.kvadrant
if (e.Y >= 0 && e.Y <= 200)
{
train_x.Add(e.X - 200);
train_y.Add(200 - e.Y);
train_exp.Add(1);
g.DrawEllipse(new Pen(Color.Red, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
//IV.kvadrant
if (e.Y >= 200 && e.Y <= 400)
{
train_x.Add(e.X - 200);
train_y.Add(e.Y - 200);
train_exp.Add(1);
g.DrawEllipse(new Pen(Color.Red, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
}
}
//Green class
if (rbtnGreen.Checked == true)
{
if (e.X >= 0 && e.X <= 200)
{
//I.kvadrant
if (e.Y >= 0 && e.Y <= 200)
{
train_x.Add(e.X - 200);
train_y.Add(200 - e.Y);
train_exp.Add(-1);
g.DrawEllipse(new Pen(Color.Green, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
//III.kvadrant
if (e.Y >= 200 && e.Y <= 400)
{
train_x.Add(e.X - 200);
train_y.Add(e.Y - 200);
train_exp.Add(-1);
g.DrawEllipse(new Pen(Color.Green, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
}
if (e.X >= 200 && e.X <= 400)
{
//II.kvadrant
if (e.Y >= 0 && e.Y <= 200)
{
train_x.Add(e.X - 200);
train_y.Add(200 - e.Y);
train_exp.Add(-1);
g.DrawEllipse(new Pen(Color.Green, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
//IV.kvadrant
if (e.Y >= 200 && e.Y <= 400)
{
train_x.Add(e.X - 200);
train_y.Add(e.Y - 200);
train_exp.Add(-1);
g.DrawEllipse(new Pen(Color.Green, 3), e.X, e.Y, 5, 5);
this.Controls.Add(pctBox);
pctBox.Image = bmp;
}
}
}
btnTrain.Enabled = true;
Týmto spôsobom bola prezentovaná jednoduchá neurónová sieť, ktorá slúži na separovanie dvoch množín jednou priamkou. Z toho vyplýva, že nie je možné separovať zložitejšie množiny, napr. množiny pre ktoré je nutné použiť viac priamok jednotlivo, resp. spoločne vo forme polygónu alebo iné geometricé útvary. Jedná sa primárne o tzv.
XOR problém, kedy na separovanie je potrebné použiť ešte jednu neurónovú vrstvu, tzv.
skrytú vrstvu.
Neurónové siete obsahujúcu skrytú vrstvu je možné považovať za zložitejšie typy neurónových sietí, ktoré budú predmetom ďalšieho článku pojednávajúceho o učení typu
Backpropagation.
0 comments:
Post a Comment