- Je normaliseert beeld-/tekstfeatures en berekent paarscores en symmetrisch contrastief verlies.
- Je onderscheidt schaal, richting, temperatuur en beide zoekrichtingen bij bekende paren.
Je hebt een foto en wilt de juiste beschrijving vinden tussen andere teksten. Een beeldvector en tekstvector kun je niet zomaar vergelijken als hun encoders verschillende ruimtes gebruiken. Contrastief leren bouwt een gedeelde vergelijkingsruimte waarin bekende paren bij elkaar moeten passen.
Denk aan twee kaartenbakken met dezelfde onderwerpen maar andere sorteercodes. De beeldencoder en tekstencoder leveren eerst hun eigen kenmerken; projecties vertalen beide naar één vectorruimte. Daarna kun je meten welke richting bij welke richting past.
CLIP gebruikt dit idee voor beelden en tekst. Wij kiezen kleine featurevectoren om de vergelijking en verliesfunctie na te rekenen; deze vectoren zijn niet door een beeld- of tekstmodel geleerd. Je implementeert drie onderdelen die bij echte training achter de encoders staan.
1. Vergelijk richting in plaats van lengte
Een vector met grote getallen hoeft niet inhoudelijk beter te passen. Deel iedere featurevector daarom door zijn lengte, de L2-norm. De resulterende eenheidsvector behoudt de richting, met lengte één.
De vector [3,4] heeft lengte vijf en wordt [0,6;0,8]. Bij [30,40] is de richting precies hetzelfde. Na normalisatie kunnen we het inproduct gebruiken als cosinusovereenkomst: één voor dezelfde richting, nul voor loodrechte richtingen en min één voor tegengestelde richtingen.
unit = normalize_rows([[3,4],[30,40]])
print(unit.round(3).tolist())
# [[0.6, 0.8], [0.6, 0.8]]
Maak normalize_rows voor een matrix met één vector per rij. Een nulvector heeft geen richting en geeft volgens ons lescontract ValueError. De gegeven vormhelpers bewaken eindige reële invoer; voorkom overloop door eerst iedere rij door zijn grootste absolute waarde te delen en pas daarna de lengte te berekenen.
012. Maak een tabel van mogelijke paren
Laat u de genormaliseerde beeldvector zijn en v de genormaliseerde tekstvector. De score S van beeld i en tekst j is hun inproduct gedeeld door een positieve temperatuur τ. Beide modaliteiten moeten dezelfde featurebreedte hebben, maar mogen verschillende aantallen voorbeelden bevatten.
Met twee loodrechte richtingen wordt de cosinustabel de identiteitsmatrix. Kies τ=0,5: delen verdubbelt de scores op de diagonaal naar twee. Een kleinere temperatuur maakt verschillen bij latere softmax scherper; het verandert de onderlinge rangorde niet.
images = [[3,0],[0,7]]
texts = [[2,0],[0,8]]
scores = cross_modal_logits(
images,texts,0.5)
print(scores.tolist())
# [[2.0, 0.0], [0.0, 2.0]]
Maak cross_modal_logits met normalisatie van beide invoeren. Gebruik onze expliciete temperatuur als deler; verwar hem niet met de leerbare log-schaalparameter uit het CLIP-paper. Deze oefenfunctie accepteert temperatuur 0,0001 tot en met 100 en begrenst ook de afgeleide scorematrix.
Beeld A en tekst A horen bij elkaar, net als B en B. Verwissel de tekstvectoren zonder de doelkoppeling op de diagonaal aan te passen.
| Beeld | Tekst A | Tekst B |
|---|---|---|
| A | 2 | 0 |
| B | 0 | 2 |
- Symmetrisch verlies
- 0,127
- Juiste indexparen
- 100%
De gemarkeerde diagonaal blijft het trainingsdoel. Een kleiner verlies betekent hier dat meer kans bij die bekende koppelingen terechtkomt.
Handgekozen rekenvoorbeelden. De getallen komen uit de eigen NumPy-functies; er is geen getrainde beeld- of tekstencoder.
3. Leer in beide zoekrichtingen
Stel dat iedere beeldrij bij de tekst met hetzelfde indexnummer hoort. In een batch van B paren zijn de diagonale combinaties positief; de andere combinaties tellen hier als negatief. Softmax over iedere rij verdeelt kansen over teksten, terwijl softmax over iedere kolom kansen over beelden verdeelt.
Neem het gemiddelde van de cross-entropy in beide richtingen. Voor iedere positieve combinatie neem je min de logaritme van zijn kans, en daarna het gemiddelde over alle paren en beide richtingen. Een verlies van nul zou alle kans op de bekende juiste koppelingen leggen.
loss = symmetric_contrastive_loss(
scores)
print(round(loss,3))
# 0.127
In onze tabel is de juiste kans ongeveer 0,881 en is het verlies ongeveer 0,127. Verwissel je de teksten zonder de indexkoppeling aan te passen, dan staat de hoogste score bij het verkeerde paar. Het verlies stijgt daardoor, ook al blijven alle vectorlengtes gelijk.
swapped = cross_modal_logits(
images,texts[::-1],0.5)
bad_loss = symmetric_contrastive_loss(
swapped)
print(round(bad_loss,3))
# 2.127
Maak symmetric_contrastive_loss met numeriek stabiele log-som-exponentberekeningen, bijvoorbeeld np.logaddexp.reduce. De invoer is vierkant omdat dit lescontract een bekende één-op-één-batchkoppeling gebruikt. In echte datasets kunnen meerdere beschrijvingen bij hetzelfde beeld passen; zulke combinaties als negatief behandelen is een beperking van dit eenvoudige verlies.
03Wat neem je mee?
- Normalisatie verwijdert lengteverschillen vóór de paarvergelijking.
- Temperatuur schaalt overeenkomsten en beïnvloedt de scherpte van softmax.
- Het symmetrische verlies beoordeelt zowel beeld-naar-tekst als tekst-naar-beeld.