- Je voegt opeenvolgende labels samen vóór je blanks verwijdert.
- Je somt begrensde uitlijningskansen en onderscheidt het beste pad van de waarschijnlijkste transcriptie.
Een lang uitgesproken klank levert meer audioframes op dan een korte. Toch wil je voor beide dezelfde letter of hetzelfde klanklabel terugkrijgen. Een herkenner heeft daarom een regel nodig om een lange rij framekeuzes om te zetten naar een kortere transcriptie.
Connectionist temporal classification, kortweg CTC, voegt daarvoor een extra klasse toe: blank. Blank betekent dat er op dat frame geen nieuw label wordt uitgestuurd. In onze voorbeelden is 0 blank, 1 het oefenlabel A en 2 het oefenlabel B.
De modeluitvoer blijft per frame een kansverdeling over alle klassen. Eerst begrijpen we hoe één gekozen klassepad een labelreeks wordt. Daarna tellen we de kansen op van verschillende paden die dezelfde transcriptie opleveren.
1. Herhalingen samenvoegen vraagt een vaste volgorde
Denk aan een aanwijzer die meerdere frames op A blijft staan. Dat is één aanhoudend label. Pas wanneer hij via blank terug naar A gaat, moet er een tweede A in de transcriptie verschijnen.
Voeg daarom eerst opeenvolgende gelijke padlabels samen en verwijder daarna de blanks. Bij het volgende pad blijven twee A's behouden, doordat er een blank tussen staat. De laatste twee B's horen bij één aanhoudend label.
path = [1,1,0,1,2,2]
print(ctc_collapse(path))
# [1, 1, 2]
Blanks vooraf verwijderen zou de twee A-groepen ten onrechte aan elkaar plakken. Je ziet de volgorde terug in dit kleine verschil: drie opeenvolgende A-frames geven één A, maar A-blank-A geeft twee A's.
print(ctc_collapse([1,1,1]))
print(ctc_collapse([1,0,1]))
# [1]
# [1, 1]
Maak ctc_collapse zonder de oorspronkelijke lijst of array te wijzigen. Een volledig blank pad levert een lege transcriptie. Blank is ook geen gewone spatie: een echte spatie zou, wanneer je die wilt herkennen, een apart betekenisvol label zijn.
012. Het waarschijnlijkste pad hoeft niet de beste reeks te geven
Greedy-decoding kiest op ieder frame de hoogste klassescore en past daarna collapse toe. Omdat softmax de volgorde van de logits bewaart, mag argmax rechtstreeks op de logits. Bij gelijke maxima kiezen we de eerste klasse.
Neem twee frames die beide blankkans 0,6 en A-kans 0,4 hebben. We kiezen logits als logaritmen van die kansen; softmax levert dan dezelfde verdeling terug. Greedy kiest tweemaal blank en geeft dus geen label.
logits = np.log([[.6,.4],[.6,.4]])
print(ctc_greedy(logits))
# []
Maar één transcriptie kan langs meerdere paden ontstaan. De vier mogelijkheden zijn hier volledig met de hand uit te schrijven. Pad AA wordt na samenvoegen één A; het stelt in dit voorbeeld dus geen dubbele A voor.
| Pad | Na collapse | Padkans | |---|---|---:| | blank, blank | leeg | 0,36 | | blank, A | A | 0,24 | | A, blank | A | 0,24 | | A, A | A | 0,16 |
De drie A-paden hebben samen kans 0,64. Dat is groter dan de kans 0,36 van de lege reeks. Greedy is snel, maar dit voorbeeld bewijst dat hij niet altijd de waarschijnlijkste transcriptie vindt.
Ieder frame kiest blank of A. Bekijk alle paden, voeg eerst herhalingen samen en verwijder daarna blanks. Tel pas dan de kansen per transcriptie op.
| Pad | Na collapse | Padkans |
|---|---|---|
| 0 0 | leeg | 0,36 |
| 0 1 | A | 0,24 |
| 1 0 | A | 0,24 |
| 1 1 | A | 0,16 |
| Transcriptie | Gesommeerde kans |
|---|---|
| leeg | 0,36 |
| A | 0,64 |
- Greedy-transcriptie
- leeg
- Hoogste reekskans
- A
Hier verschillen de uitkomsten: greedy kiest het beste afzonderlijke pad, maar meerdere andere paden steunen samen een waarschijnlijkere transcriptie. Voor AA zijn minstens drie frames nodig: A, blank, A.
0 betekent blank, 1 betekent A. Blank is geen spatie. De framekansen zijn hier op ieder tijdstip gelijk; de padkans is het product van de gekozen framekansen.
3. Som kansen van uitlijningen, geen logits
Een klassepad π kiest op ieder tijdstip t één klasse. Als p de modelkansen zijn, is zijn padkans het product van de gekozen framekansen. CTC gebruikt deze factorisatie gegeven de modelinvoer x.
Voor de kans van doelreeks l tel je alle passende padkansen op. Het pijltje onder de som betekent dat het pad na collapse precies l moet opleveren. Een hoog scorend maar verkeerd pad telt dus niet mee.
Maak ctc_enumerated_log_probability met de gegeven stabiele logkansen. Som passende paden met logaddexp, zodat kleine producten niet voortijdig verdwijnen. Exp van de geretourneerde logkans maakt ons handantwoord weer zichtbaar.
log_p = ctc_enumerated_log_probability(
logits,[1])
print(round(float(np.exp(log_p)),2))
# 0.64
Begrens enumeratie tot 4096 paden: het aantal groeit als C tot de macht T. Een dubbele A heeft minstens drie frames nodig, omdat een blank de twee A's moet scheiden. De validator weigert een onmogelijk kort doel voordat je paden doorloopt.
03Wat neem je mee?
- De volgorde van samenvoegen en blankverwijdering bepaalt het antwoord.
- Een transcriptiekans telt meerdere mogelijke uitlijningen bij elkaar op.
- Greedy is een benadering; volledige enumeratie groeit te snel voor lange audio.
Hierna bereken je dezelfde doelskans met een compacte dynamische tabel.