7.13. Non-max suppression

Tunnistusverkko tuottaa tyypillisesti useita päällekkäisiä ehdokaslaatikoita saman reaalimaailman kohteen ympärille: jokainen kohteen lähellä oleva ankkuri laukeaa samankaltaisella pisteytyksellä, ja jälkikäsittelijä näkee ne kaikki. Non-max suppression (NMS) on vaihe, joka muuntaa tämän rykelmän yhdeksi laatikoksi.

Algoritmi on lyhyt: lajittele ehdokaslaatikot pisteytyksen mukaan, ota korkeimman pisteytyksen saanut, vaimenna kaikki muut laatikot, jotka menevät päällekkäin sen kanssa yli valitun kynnysarvon, ota sitten seuraavaksi korkein jäljelle jääneistä ja toista. Päällekkäisyyden mittari on intersection-over-union (IoU) – kahden laatikon yhteinen pinta-ala jaettuna niiden yhteenlasketulla pinta-alalla, arvo välillä 0 (ei päällekkäisyyttä) ja 1 (identtiset laatikot). Jokaisen mukana toimitetun jälkikäsittelijän nms_threshold-konstruktoriargumentti on raja-arvo, jonka ylittäviä laatikoita käsitellään jo säilytetyn laatikon kaksoiskappaleina.

Vasemmalla kolme päällekkäistä rajauslaatikkoa yhden kohteen ympärillä, merkittyinä pisteytyksillä 0.92, 0.83 ja 0.71. Nuoli osoittaa oikealle, missä yksi säilynyt laatikko jää jäljelle pisteytyksellä 0.92. Kaksi matalamman pisteytyksen laatikkoa vaimentaa korkeamman pisteytyksen laatikko, koska niiden intersection-over-union sen kanssa ylittää kynnysarvon.

NMS tiivistää päällekkäisten tunnistusten rykelmän korkeimman pisteytyksen saaneeseen.

7.13.1. Soft-NMS

Mukana toimitettu ml.utils.NMS-luokka toteuttaa Soft-NMS-menetelmän, hienosäädön, joka pienentää päällekkäisen laatikon pisteytystä sen mukaan, kuinka paljon se menee päällekkäin, sen sijaan että pudottaisi laatikon kokonaan pois. Jos pienennetty pisteytys jää kynnysarvon alle, laatikko pudotetaan; muuten se säilyy pienennetyllä pisteytyksellä ja kilpailee seuraavalla kierroksella.

nms_sigma-parametri ohjaa sitä, kuinka aggressiivinen vaimennus on. Pienellä nms_sigma-arvolla (mukana toimitettu oletus 0.1) vaimennus on jyrkkä: voimakkaasti päällekkäisen laatikon pisteytys ajetaan lähes nollaan ja Soft-NMS pelkistyy klassiseksi NMS:ksi. Suuremmalla nms_sigma-arvolla vaimennus on lievä ja eri kohteiden päällekkäiset laatikot säilyvät useammin, millä on merkitystä, kun saman luokan reaalimaailman kohteet aidosti menevät päällekkäin (kasvojen joukko, kämmenten rykelmä).

nms_sigma-arvon asettaminen <= 0 poistaa vaimennuksen kokonaan käytöstä: päällekkäiset laatikot kulkevat läpi alkuperäisillä pisteytyksillään, ja vain pisteytyksen kynnysarvo suodattaa ne.

7.13.2. Sellaisen rakentaminen suoraan

Jokainen mukana toimitettu jälkikäsittelijä rakentaa tuoreen NMS-olion jokaista päättelyä varten, lisää siihen jokaisen ehdokkaan ja kutsuu lopuksi get_bounding_boxes(). Mukautettu jälkikäsittelijä noudattaa samaa kaavaa:

from ml.utils import NMS

iw = model.input_shape[0][2]
ih = model.input_shape[0][1]

nms = NMS(iw, ih, inputs[0].roi)
for box, score, class_idx in candidates:
    nms.add_bounding_box(box.xmin, box.ymin,
                         box.xmax, box.ymax,
                         score, class_idx)
result = nms.get_bounding_boxes(threshold=nms_threshold,
                                sigma=nms_sigma)

Konstruktori ottaa verkon syötteen leveyden ja korkeuden pikseleinä sekä sen alkuperäisen kuvan ROI:n, jota vasten malli ajettiin; add_bounding_box() ottaa laatikon koordinaatit kyseisessä verkon syötteen pikseliavaruudessa, ja get_bounding_boxes() kuvaa säilyneet takaisin kuvan koordinaatteihin käyttäen ROI:ta. Uudelleenkuvaus ottaa huomioon Normalisoinnin venytyksen automaattisesti – samaa ROI:ta, jonka ennustaja näki, käytetään laatikoiden projisoimiseen takaisin – joten palautetut laatikot ovat valmiita piirrettäviksi kaapatulle kehykselle.

Palautuksen muoto on listoista koostuva lista luokkakohtaisia listoja, indeksoituna add_bounding_box-funktiolle välitetyllä label_index-arvolla. Tyhjät luokkalistat säilytetään, jotta indeksi vastaa mallin luokkaindeksiä; enumerate(result) käy luokat läpi yhdessä niiden tunnistusten kanssa.