stub En fullständig guide för att finjustera stora språkmodeller - Unite.AI
Anslut dig till vårt nätverk!

Artificiell intelligens

En fullständig guide för att finjustera stora språkmodeller

mm
Uppdaterad on

Stora språkmodeller (LLM) som GPT-4, LaMDA, PaLM och andra har tagit världen med storm med sin anmärkningsvärda förmåga att förstå och generera människoliknande text om ett stort antal ämnen. Dessa modeller är förtränade på massiva datamängder som består av miljarder ord från internet, böcker och andra källor.

Denna förträningsfas genomsyrar modellerna med omfattande allmän kunskap om språk, ämnen, resonemangsförmåga och till och med vissa fördomar som finns i träningsdatan. Men trots sin otroliga bredd saknar dessa förutbildade LLM specialiserad expertis för specifika domäner eller uppgifter.

Det är här finjustering kommer in – processen att anpassa en förutbildad LLM för att utmärka sig i en viss applikation eller användningsfall. Genom att vidareutbilda modellen på en mindre, uppgiftsspecifik datauppsättning kan vi justera dess kapacitet för att anpassas till nyanserna och kraven för den domänen.

Finjustering är analogt med att överföra den breda kunskapen hos en högutbildad generalist för att skapa en ämnesexpert specialiserad på ett visst område. I den här guiden kommer vi att utforska vad, varför och hur för att finjustera LLM:er.

Finjustera stora språkmodeller

Finjustera stora språkmodeller

Vad är finjustering?

I sin kärna, finjustering innebär att ta en stor förtränad modell och uppdatera dess parametrar med hjälp av en andra träningsfas på en datauppsättning som är skräddarsydd för din måluppgift eller domän. Detta gör att modellen kan lära sig och internalisera nyanser, mönster och mål som är specifika för det smalare området.

Medan förutbildning fångar bred språkförståelse från en enorm och mångsidig textkorpus, specialiserar finjustering den allmänna kompetensen. Det är som att ta en renässansman och forma dem till en branschexpert.

Den förtränade modellens vikter, som kodar dess allmänna kunskaper, används som utgångspunkt eller initialisering för finjusteringsprocessen. Modellen tränas sedan vidare, men denna gång på exempel som är direkt relevanta för slutapplikationen.

Genom att exponera modellen för denna specialiserade datadistribution och justera modellparametrarna därefter, gör vi LLM mer exakt och effektiv för målanvändningsfallet, samtidigt som vi drar nytta av de breda förutbildade kapaciteterna som en grund.

Varför finjustera LLM:er?

Det finns flera viktiga skäl till varför du kanske vill finjustera en stor språkmodell:

  1. Domänanpassning: Varje område, från juridik till medicin till mjukvaruteknik, har sina egna nyanserade språkkonventioner, jargong och sammanhang. Finjustering låter dig anpassa en generell modell för att förstå och producera text anpassad till den specifika domänen.
  2. Uppgiftsspecialisering: LLM:er kan finjusteras för olika naturliga språkbehandlingsuppgifter som textsammanfattning, maskinöversättning, frågesvar och så vidare. Denna specialisering ökar prestandan på måluppgiften.
  3. Uppfyllelse av uppgifter: Högt reglerade branscher som sjukvård och finans har stränga datasekretesskrav. Finjustering gör det möjligt att utbilda LLM:er i proprietära organisationsdata samtidigt som känslig information skyddas.
  4. Begränsad märkt data: Att skaffa stora märkta datamängder för att träna modeller från grunden kan vara utmanande. Finjustering gör det möjligt att uppnå stark uppgiftsprestanda från begränsade övervakade exempel genom att utnyttja den förtränade modellens kapacitet.
  5. Modelluppdatering: När ny data blir tillgänglig med tiden i en domän kan du finjustera modellerna ytterligare för att införliva den senaste kunskapen och kapaciteten.
  6. Förmildrande fördomar: LLM kan plocka upp samhälleliga fördomar från breda data före utbildningen. Finjustering av utvalda datauppsättningar kan hjälpa till att minska och korrigera dessa oönskade fördomar.

I huvudsak överbryggar finjustering gapet mellan en allmän, bred modell och de fokuserade kraven för en specialiserad applikation. Det förbättrar noggrannheten, säkerheten och relevansen av modellutgångar för riktade användningsfall.

Finjustera stora språkmodeller

Finjustera stora språkmodeller

Det medföljande diagrammet beskriver processen för att implementera och använda stora språkmodeller (LLM), specifikt för företagsapplikationer. Inledningsvis matas en förtränad modell som T5 strukturerad och ostrukturerad företagsdata, som kan komma i olika format som CSV eller JSON. Dessa data genomgår övervakade, oövervakade eller överföringsfinjusteringsprocesser, vilket förbättrar modellens relevans för företagets specifika behov.

När modellen är finjusterad med företagsdata uppdateras dess vikter därefter. Den utbildade modellen itererar sedan genom ytterligare utbildningscykler, och förbättrar kontinuerligt sina svar över tiden med nya företagsdata. Processen är iterativ och dynamisk, med modellen lärande och omskolning för att anpassa sig till förändrade datamönster.

Utdata från denna tränade modell – tokens och inbäddningar som representerar ord – distribueras sedan för olika företagsapplikationer. Dessa applikationer kan sträcka sig från chatbots till sjukvård, var och en kräver att modellen förstår och svarar på branschspecifika frågor. Inom ekonomi inkluderar tillämpningar bedrägeriupptäckt och hotanalys; inom vården kan modeller bistå med patientförfrågningar och diagnostik.

Den utbildade modellens förmåga att bearbeta och svara på ny företagsdata över tid säkerställer att dess användbarhet bibehålls och växer. Som ett resultat kan företagsanvändare interagera med modellen genom applikationer, ställa frågor och få informerade svar som återspeglar modellens utbildning och finjustering av domänspecifika data.

Den här infrastrukturen stöder ett brett utbud av företagsapplikationer, som visar mångsidigheten och anpassningsförmågan hos LLM:er när de är korrekt implementerade och underhållna i ett affärssammanhang.

Finjusteringsmetoder

Det finns två primära strategier när det gäller att finjustera stora språkmodeller:

1) Full modellfinjustering

I den fullständiga finjusteringsmetoden uppdateras alla parametrar (vikter och fördomar) för den förtränade modellen under den andra träningsfasen. Modellen exponeras för den uppgiftsspecifika märkta datamängden, och standardutbildningsprocessen optimerar hela modellen för den datadistributionen.

Detta gör att modellen kan göra mer omfattande justeringar och anpassa sig holistiskt till måluppgiften eller domänen. Full finjustering har dock några nackdelar:

  • Det kräver betydande beräkningsresurser och tid att träna, liknande förträningsfasen.
  • Lagringskraven är höga, eftersom du behöver ha en separat finjusterad kopia av modellen för varje uppgift.
  • Det finns en risk för "katastrofisk glömska", där finjustering gör att modellen tappar vissa allmänna förmågor som lärts under förträningen.

Trots dessa begränsningar förblir full finjustering en kraftfull och allmänt använd teknik när resurserna tillåter och måluppgiften avviker avsevärt från det allmänna språket.

2) Effektiva finjusteringsmetoder

För att övervinna de beräkningsmässiga utmaningarna med full finjustering har forskare utvecklat effektiva strategier som bara uppdaterar en liten delmängd av modellens parametrar under finjustering. Dessa parametriskt effektiva tekniker skapar en balans mellan specialisering och minskade resurskrav.

Några populära effektiva finjusteringsmetoder inkluderar:

Prefix-Tuning: Här introduceras och tränas ett litet antal uppgiftsspecifika vektorer eller "prefix" för att konditionera den förtränade modellens uppmärksamhet för måluppgiften. Endast dessa prefix uppdateras under finjustering.

LoRA (lågrankad anpassning): LoRA injicerar träningsbara lågrankade matriser i varje lager av den förtränade modellen under finjustering. Dessa små rangjusteringar hjälper till att specialisera modellen med mycket färre träningsbara parametrar än full finjustering.

Visst, jag kan ge en detaljerad förklaring av LoRA (Low-Rank Adaptation) tillsammans med den matematiska formuleringen och kodexemplen. LoRA är en populär parametereffektiv finjusteringsteknik (PEFT) som har vunnit betydande dragkraft inom området för anpassning av stora språkmodeller (LLM).

Vad är LoRA?

LoRA är en finjusteringsmetod som introducerar ett litet antal träningsbara parametrar till den förtränade LLM, vilket möjliggör effektiv anpassning till nedströmsuppgifter samtidigt som majoriteten av den ursprungliga modellens kunskap bevaras. Istället för att finjustera alla parametrar för LLM, injicerar LoRA uppgiftsspecifika lågrankade matriser i modellens lager, vilket möjliggör betydande beräknings- och minnesbesparingar under finjusteringsprocessen.

Matematisk formulering

LoRA (Low-Rank Adaptation) är en finjusteringsmetod för stora språkmodeller (LLM) som introducerar en lågrankad uppdatering av viktmatriserna. För en viktmatris 0∈, lägger LoRA till en matris med låg rangordning , med och Där är rangen. Detta tillvägagångssätt minskar avsevärt antalet träningsbara parametrar, vilket möjliggör effektiv anpassning till nedströmsuppgifter med minimala beräkningsresurser. Den uppdaterade viktmatrisen ges av .

Denna lågrankade uppdatering kan tolkas som en modifiering av den ursprungliga viktmatrisen $W_{0}$ genom att lägga till en lågrankad matris $BA$. Den viktigaste fördelen med denna formulering är att istället för att uppdatera alla $d \times k$ parametrar i $W_{0}$, behöver LoRA bara optimera $r \times (d + k)$ parametrar i $A$ och $B $, vilket avsevärt minskar antalet träningsbara parametrar.

Här är ett exempel i Python som använder peft bibliotek för att tillämpa LoRA på en förutbildad LLM för textklassificering:

</div>
<div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color="">from</span> transformers <span class="token" data-darkreader-inline-color="">import</span> AutoModelForSequenceClassification
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color="">from</span> peft <span class="token" data-darkreader-inline-color="">import</span> get_peft_model<span class="token" data-darkreader-inline-color="">,</span> LoraConfig<span class="token" data-darkreader-inline-color="">,</span> TaskType
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># Load pre-trained model</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">model <span class="token" data-darkreader-inline-color="">=</span> AutoModelForSequenceClassification<span class="token" data-darkreader-inline-color="">.</span>from_pretrained<span class="token" data-darkreader-inline-color="">(</span><span class="token" data-darkreader-inline-color="">"bert-base-uncased"</span><span class="token" data-darkreader-inline-color="">,</span> num_labels<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">2</span><span class="token" data-darkreader-inline-color="">)</span>
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># Define LoRA configuration</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">peft_config <span class="token" data-darkreader-inline-color="">=</span> LoraConfig<span class="token" data-darkreader-inline-color="">(</span>task_type<span class="token" data-darkreader-inline-color="">=</span>TaskType<span class="token" data-darkreader-inline-color="">.</span>SEQ_CLS<span class="token" data-darkreader-inline-color="">, </span>r<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">8</span><span class="token" data-darkreader-inline-color="">,</span>  <span class="token" data-darkreader-inline-color=""># Rank of the low-rank update</span>
lora_alpha<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">16</span><span class="token" data-darkreader-inline-color="">,</span></code><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># Scaling factor for the low-rank update</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">    target_modules<span class="token" data-darkreader-inline-color="">=</span><span class="token" data-darkreader-inline-color="">[</span><span class="token" data-darkreader-inline-color="">"q_lin"</span><span class="token" data-darkreader-inline-color="">,</span> <span class="token" data-darkreader-inline-color="">"v_lin"</span><span class="token" data-darkreader-inline-color="">]</span><span class="token" data-darkreader-inline-color="">,</span>  <span class="token" data-darkreader-inline-color=""># Apply LoRA to the query and value layers</span>
<span class="token" data-darkreader-inline-color="">)</span>
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># Create the LoRA-enabled model</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">model <span class="token" data-darkreader-inline-color="">=</span> get_peft_model<span class="token" data-darkreader-inline-color="">(</span>model<span class="token" data-darkreader-inline-color="">,</span> peft_config<span class="token" data-darkreader-inline-color="">)</span>
</code></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># Fine-tune the model with LoRA</span>
</code></div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""></div>
<div class="code-block__code !my-0 !rounded-t-lg !text-sm !leading-relaxed" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><code class="language-python" data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color=""><span class="token" data-darkreader-inline-color=""># ... (training code omitted for brevity)</span></code></div>
</div>
<div data-darkreader-inline-bgimage="" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">

I det här exemplet laddar vi en förtränad BERT-modell för sekvensklassificering och definierar en LoRA-konfiguration. De r parametern anger rangen för uppdateringen med låg rang, och lora_alpha är en skalningsfaktor för uppdateringen. De target_modules parametern indikerar vilka lager av modellen som ska ta emot lågrankade uppdateringar. Efter att ha skapat den LoRA-aktiverade modellen kan vi fortsätta med finjusteringsprocessen med hjälp av standardutbildningsproceduren.

Adapterlager: Liknar LoRA, men istället för lågrankade uppdateringar, infogas tunna "adapter"-lager i varje transformatorblock i den förtränade modellen. Endast parametrarna för dessa få nya kompakta lager tränas.

Snabb inställning: Detta tillvägagångssätt håller den förtränade modellen frusen helt. Istället introduceras träningsbara "prompt" inbäddningar som input för att aktivera modellens förtränade kunskaper för måluppgiften.

Dessa effektiva metoder kan ge upp till 100x beräkningsminskningar jämfört med full finjustering, samtidigt som de uppnår konkurrenskraftiga prestanda för många uppgifter. De minskar också lagringsbehovet genom att undvika full modellduplicering.

Däremot kan deras prestanda släpa efter full finjustering för uppgifter som skiljer sig mycket från det allmänna språket eller kräver mer holistisk specialisering.

Finjusteringsprocessen

Oavsett finjusteringsstrategin följer den övergripande processen för att specialisera en LLM en generell ram:

  1. Dataset Förberedelse: Du måste skaffa eller skapa en märkt datauppsättning som mappar ingångar (prompter) till önskade utdata för din måluppgift. För textgenereringsuppgifter som summering skulle detta vara inmatningstext till sammanfattade utdatapar.
  2. Datauppdelning: Följ bästa praxis och dela upp din märkta datauppsättning i tåg-, validerings- och testuppsättningar. Detta separerar data för modellträning, hyperparameterinställning och slutlig utvärdering.
  3. Inställning av hyperparameter: Parametrar som inlärningshastighet, batchstorlek och träningsschema måste justeras för den mest effektiva finjusteringen av dina data. Detta innebär vanligtvis en liten valideringsuppsättning.
  4. Modellutbildning: Använd de inställda hyperparametrarna och kör finjusteringsoptimeringsprocessen på hela träningsuppsättningen tills modellens prestanda på valideringsuppsättningen slutar förbättras (tidigt avbrytande).
  5. Utvärdering: Bedöm den finjusterade modellens prestanda på den uthållna testuppsättningen, som helst omfattar verkliga exempel för målanvändningsfallet, för att uppskatta verklig effektivitet.
  6. Utplacering och övervakning: När den är tillfredsställande kan den finjusterade modellen användas för slutsatser om nya ingångar. Det är avgörande att övervaka dess prestanda och noggrannhet över tid för konceptdrift.

Även om detta beskriver den övergripande processen, kan många nyanser påverka finjusteringsframgången för en viss LLM eller uppgift. Strategier som läroplansinlärning, finjustering av flera uppgifter och få-shot-uppmaning kan ytterligare öka prestandan.

Dessutom kräver effektiva finjusteringsmetoder extra hänsyn. Till exempel kräver LoRA tekniker som att konditionera de förtränade modellutgångarna genom ett kombinerande lager. Snabb inställning kräver noggrant utformade uppmaningar för att aktivera rätt beteenden.

Avancerad finjustering: Inkorporering av mänsklig feedback

Även om standardövervakad finjustering med hjälp av märkta datauppsättningar är effektiv, är en spännande gräns att utbilda LLM:er direkt med hjälp av mänskliga preferenser och feedback. Denna human-in-the-loop-metod utnyttjar tekniker från förstärkningsinlärning:

PPO (Proximal policyoptimering): Här behandlas LLM som en förstärkningsinlärningsagent, med dess resultat som "åtgärder". En belöningsmodell tränas för att förutsäga mänskliga betyg eller kvalitetspoäng för dessa resultat. PPO optimerar sedan LLM för att generera utdata som maximerar belöningsmodellens poäng.

RLHF (Förstärkning Lärande av mänsklig feedback): Detta utökar PPO genom att direkt införliva mänsklig feedback i inlärningsprocessen. Istället för en fast belöningsmodell kommer belöningarna från iterativa mänskliga utvärderingar av LLM:s resultat under finjustering.

Även om de är beräkningsintensiva tillåter dessa metoder att forma LLM-beteende mer exakt baserat på önskade egenskaper utvärderade av människor, utöver vad som kan fångas i en statisk datauppsättning.

Företag som Anthropic använde RLHF för att genomsyra sina språkmodeller som Claude med förbättrad sanningsenlighet, etik och säkerhetsmedvetenhet utöver bara uppgiftskompetens.

Potentiella risker och begränsningar

Även om det är oerhört kraftfullt, är finjusterande LLM:er inte utan risker som måste hanteras noggrant:

Bias Amplifiering: Om finjusteringsdata innehåller samhälleliga fördomar kring kön, ras, ålder eller andra attribut, kan modellen förstärka dessa oönskade fördomar. Att kurera representativa och neutrala datauppsättningar är avgörande.

Faktadrift: Även efter finjustering av data av hög kvalitet kan språkmodeller "hallucinera" felaktiga fakta eller utdata som inte överensstämmer med träningsexemplen över längre samtal eller uppmaningar. Faktasökningsmetoder kan behövas.

Skalbarhetsutmaningar: Fullständig finjustering av enorma modeller som GPT-3 kräver enorma beräkningsresurser som kan vara omöjliga för många organisationer. Effektiv finjustering mildrar detta delvis men har kompromisser.

Katastrofal glömska: Under full finjustering kan modeller uppleva katastrofala glömska, där de förlorar några allmänna förmågor som lärts under förträning. Fleruppgiftsinlärning kan behövas.

IP och integritetsrisker: Proprietär data som används för finjustering kan läcka in i offentligt släppta språkmodeller, vilket utgör risker. Olika tekniker för att begränsa sekretess och informationsrisker är aktiva forskningsområden.

Sammantaget, även om det är exceptionellt användbart, är finjustering en nyanserad process som kräver omsorg kring datakvalitet, identitetsöverväganden, att minska risker och balansera avvägningar mellan prestanda och effektivitet baserat på användningsfallskrav.

Framtiden: anpassning av språkmodeller i skala

Framöver kommer framsteg inom finjustering och modellanpassningstekniker att vara avgörande för att frigöra den fulla potentialen hos stora språkmodeller över olika applikationer och domäner.

Effektivare metoder som möjliggör finjustering av även större modeller som PaLM med begränsade resurser skulle kunna demokratisera åtkomsten. Automatisering av pipelines för att skapa dataset och snabb konstruktion kan effektivisera specialisering.

Självkontrollerade tekniker för att finjustera från rådata utan etiketter kan öppna nya gränser. Och sammansättningsmetoder för att kombinera finjusterade undermodeller som tränats på olika uppgifter eller data skulle kunna göra det möjligt att konstruera mycket skräddarsydda modeller på begäran.

I slutändan, när LLM:er blir mer allmänt förekommande, kommer möjligheten att anpassa och specialisera dem sömlöst för alla tänkbara användningsfall att vara avgörande. Finjustering och relaterade modellanpassningsstrategier är centrala steg för att förverkliga visionen om stora språkmodeller som flexibla, säkra och kraftfulla AI-assistenter som utökar mänskliga förmågor över alla domäner och strävanden.

Jag har ägnat de senaste fem åren åt att fördjupa mig i den fascinerande världen av Machine Learning och Deep Learning. Min passion och expertis har lett mig till att bidra till över 50 olika programvaruutvecklingsprojekt, med särskilt fokus på AI/ML. Min pågående nyfikenhet har också dragit mig mot Natural Language Processing, ett område som jag är ivrig att utforska vidare.