micro:bit prepoznaje pokrete
micro:bit ima ugrađen akcelerometar koji meri ubrzanje po tri ose. U ovoj lekciji micro:bit sam uči da razlikuje pokrete – mirovanje, mahanje i tresenje. Sve se dešava na samoj ploči: učenje, pamćenje primera i prepoznavanje. Koristimo algoritam najbližeg suseda iz modula 3, napisan u MicroPythonu.
Šta nam treba
Ideja: osobine pokreta
Jedno merenje akcelerometra (x, y, z) ne govori mnogo – važno je kako se ubrzanje menja tokom pokreta. Zato micro:bit pola sekunde meri 25 puta i za svaku osu izračuna rasipanje (standardnu devijaciju) – koliko su se vrednosti razlikovale od proseka:
- mirovanje: vrednosti se skoro ne menjaju – sva tri broja su mala;
- mahanje: velika promena po jednoj osi (levo–desno), male po ostalim;
- tresenje: velike promene po svim osama.
Tri broja rasipanja su osobine pokreta, a broj klase (0, 1, 2) je oznaka.
Program
# micro:bit uči pokrete: algoritam najbližeg suseda (k-NN) u MicroPythonu
# Klase: 0 = mirno, 1 = mahanje, 2 = tresenje
# UČENJE: B – sledeća klasa, A – snimi primer trenutne klase (pomeraj micro:bit 0,5 s)
# A i B zajedno – kraj učenja, počinje prepoznavanje
from microbit import *
import math
BROJ_KLASA = 3
primeri = [] # lista parova (osobine, klasa)
klasa = 0
ucenje = True
def rasipanje(vrednosti):
"""Koliko se vrednosti razlikuju od proseka (standardna devijacija)."""
s = sum(vrednosti) / len(vrednosti)
return math.sqrt(sum((v - s) ** 2 for v in vrednosti) / len(vrednosti))
def osobine():
"""Meri 0,5 s i vraća tri broja: koliko se menjalo ubrzanje po osama x, y i z."""
xs, ys, zs = [], [], []
for i in range(25):
x, y, z = accelerometer.get_values()
xs.append(x)
ys.append(y)
zs.append(z)
sleep(20)
return [rasipanje(xs), rasipanje(ys), rasipanje(zs)]
def knn(o, k=3):
"""Klasa koju ima većina od k najbližih snimljenih primera."""
sortirano = sorted(primeri, key=lambda p: sum((a - b) ** 2 for a, b in zip(o, p[0])))
glasovi = [0] * BROJ_KLASA
for _, c in sortirano[:k]:
glasovi[c] += 1
return glasovi.index(max(glasovi))
display.show(klasa)
while True:
if ucenje:
if button_a.is_pressed() and button_b.is_pressed():
ucenje = False
button_a.was_pressed() # brišemo zapamćene pritiske
button_b.was_pressed()
display.scroll("GO")
elif button_b.was_pressed():
klasa = (klasa + 1) % BROJ_KLASA
display.show(klasa)
elif button_a.was_pressed():
display.show(Image.DIAMOND_SMALL) # znak da snimamo
primeri.append((osobine(), klasa))
display.show(klasa)
else:
if len(primeri) < 3:
display.scroll("MALO PRIMERA")
ucenje = True
display.show(klasa)
else:
display.show(knn(osobine()))
sleep(50)
Kako se koristi
- Na ekranu je 0 (mirno). Drži micro:bit mirno i pritisni A – pojavi se mali romb dok traje snimanje (0,5 s). Snimi 4–5 primera.
- Pritisni B – na ekranu je 1 (mahanje). Pritisni A i odmah mahni levo-desno. Ponovi 4–5 puta.
- Pritisni B – 2 (tresenje). Snimi 4–5 primera tresenja.
- Pritisni A i B zajedno – piše „GO“ i micro:bit počinje da prepoznaje: na ekranu je broj pokreta koji radiš.
Program smo proverili simulacijom na računaru (sa izmišljenim vrednostima akcelerometra): posle 12 snimljenih primera prepoznavao je sva tri pokreta. Na pravom micro:bit-u isprobaj koliko primera ti treba.
Šta se dešava „ispod haube“
- Lista
primerije ceo „model“: k-NN samo pamti primere. Kada se micro:bit isključi, primeri se brišu – svako pokretanje je novo učenje. - Svakih pola sekunde micro:bit izmeri novi pokret, izračuna tri broja i uporedi ih sa svim snimljenim primerima.
- micro:bit V1 ima samo 16 KB radne memorije, ali za nekoliko desetina primera od po tri broja to je sasvim dovoljno.
Parovi treniraju svoje micro:bit-e, pa ih razmene: da li model koji je naučio jedan učenik prepoznaje pokrete drugog? Diskusija: zašto je dobro da u podacima budu pokreti više ljudi.
Česte zablude
- „micro:bit je premali za veštačku inteligenciju“ – za jednostavne zadatke (pokreti, zvuk, nagib) mali modeli rade i na veoma malim čipovima.
- „Model prepoznaje bilo koji pokret“ – prepoznaje samo pokrete kojima ga je neko naučio; sve ostalo svrsta u najsličniju klasu.
Zadaci za vežbu
Pokušaj prvo sam, pa tek onda otvori rešenje.
- Dodaj četvrti pokret – „skok“. Šta treba promeniti u programu?
- Umesto brojeva prikazuj sličice: mirno –
Image.ASLEEP, mahanje –Image.HAPPY, tresenje –Image.SURPRISED. - Zašto koristimo rasipanje vrednosti, a ne same vrednosti x, y i z?
Rešenje 1: rešenje
Dovoljno je promeniti BROJ_KLASA = 3 u BROJ_KLASA = 4. Dugme B tada ide kroz klase 0, 1, 2, 3, a lista glasovi se pravi za 4 klase. Snimi primere skoka (micro:bit u ruci ili na nozi) kao klasu 3.
Rešenje 2: rešenje
Na početku programa dodaj SLICICE = [Image.ASLEEP, Image.HAPPY, Image.SURPRISED], a u režimu prepoznavanja umesto display.show(knn(osobine())) napiši display.show(SLICICE[knn(osobine())]).
Rešenje 3: objašnjenje
Same vrednosti zavise od toga kako držiš micro:bit (nagnut, uspravan), pa bi isti pokret izgledao različito. Rasipanje meri koliko se ubrzanje menja tokom pokreta, a to malo zavisi od položaja – zato je bolja osobina za prepoznavanje pokreta.
