Google | Programování

Analyzovali jsme emoce ve vítězném oscarovém filmu Země nomádů pomocí Google Cloud

  • Tentokrát si vyzkoušíme Cloud Natural Language API od Googlu
  • Pomocí Apps Scriptu zjistíme emoce
  • Pomohou nám v tom anglické titulky z OpenSubtitles

...a Oskara za nejlepší film získává...

Včera jsme se dozvěděli, že podle americké Akademie filmového umění a věd je nejlepší snímkem roku 2020 film Země nomádů.

Existuje plno indikátorů, podle kterých by se dal odhadnout nejlepší film. Jedním z nich jsou bezpochyby emoce, které hrají ve filmu hlavní roli; jejich množství, rozložení či změna. Právě proto scénáristé využívají ty správné techniky tak, aby emoce zanechaly v divácích hluboký dojem i po skončení filmu.

 

Ivan Kutil

Autor článku působí jako CTO a Google Cloud Architect ve firmě AppSatori. Ve své práci předvádí, že technologie „umělé inteligence“ jsou snadno dostupné a dají se využívat i zábavným způsobem. Krásným příkladem je využití Google Cloud AI k hledání odpovědí v televizní soutěži Kalendárium.

Analýza titulků v cloudu

Demokratizace A.I. (či M.L. v tomto případě) vede k přístupnějším algoritmům, které dříve byly k dispozici hlavně pro vědecké výzkumníky nebo firmy s velkými rozpočty. I díky tomu je oblast zpracování přirozeného jazyka (Natural Language Processing) k dispozici téměř pro kohokoliv, kdo potřebuje analyzovat jazykovou syntaxi, identifikovat objekty v textu nebo právě k analýze emocí (sentimentu).

4703256c-6629-428b-b1d1-1907b05c594c
Cloud Natural Language API pro analýzu textů na serverech Googlu

Velké firmy jako Google, Microsoft či Amazon investují obrovské částky na vylepšení svých algoritmů, které pak poskytují ostatním formou služby zpravidla skrze aplikační rozhraní.

Díky API tak můžeme jednoduše analyzovat texty, a protože filmové titulky tuto funkci splňují, můžeme z nich v čase zjistit, jak se v průběhu filmu mění emoce. Dnes si to vyzkoušíme právě na vítězné Zemi nomádů a jejích komunitních anglických titulcích. 

2255c280-0429-4c38-8b32-5c4d531460f3
Anglické titulky k Nomadland stažené na Google Drive

Nejdříve si proto uložíme anglické titulky ze serveru OpenSubtitles ve formátu .srt a nahrajeme je na Google Disk.

Google Cloud ovládneme z Disku 

V dalším kroku vytvoříme nový Google Apps Script, který je vhodný pro automatizaci a prototypování aplikací. Vývoj, spuštění a případné nasazení probíhá komplet ve webovém prohlížeči, takže si nemusíte nic instalovat.

1f118789-f624-49bf-8fc0-301d045a5909
Skript můžeme vytvořit jako nový dokument přímo na Disku, anebo jako na obrázku výše skrze jeho web script.google.com. I ten poté bude dostupný z úložiště Google Drive. 

Apps Scriptem sice vše zprovozníme, samotnou analýzu ale provede projekt na Google Cloud Platform, který slouží pro aktivaci a nastavení profesionálních cloudových služeb firmy. Výhodou Google Apps Scriptu je, že vám tento GCP projekt vytvoří automaticky spolu s Apps Scriptem.

Základ zdarma

V konzoli projektu aktivujeme Cloud Natural Language API, do kterého se budou posílat texty pro analýzu. Cena za využívání je nastavena za zpracovaný dokument s 1 000 textovými znaky v rámci jednoho API dotazu.

Měsíčně máte zdarma až 5 000 dotazů, respektive 5 000 dokumentů, a každý s 1 000 znaky. Poté se platí dle přiloženého ceníku. Takže po překročení bezplatného limitu budete platit 1 dolar za 1 000 dokumentů (každý s 1 000 znaky).

bbca3479-3bf1-483d-abbe-13b4f3c304dc
Jazykové API stačí dohledat a aktivovat v konzoli Google Cloud

Aktivaci API z konzole Google Cloudu provedeme v nabídce API & Services →  Library →  Cloud Natural Language API → Enable.

API vyžaduje aktivní platební účet pro případ, že byste překročili kvótu zdarma. Po založení nového účtu ale získáte kredit 300 dolarů po dobu 90 dní, což se hodí pro další a náročnější experimentování. Pokud chcete využívat cloudových služeb Googlu, ale nechcete vyplňovat údaje o své platební kartě, můžete se ozvat některému z českých partnerů (třeba AppSatori).

Ještě potřebujeme klíč k API

Ještě potřebujeme API klíč, který identifikuje náš projekt při volání jazykové analýzy. Získáte jej v nastavení projektu na Google Cloud v sekci API & Services → Credentials →  Create credentials →  API key.  V ostrém veřejném nasazení by bylo vhodné nastavit i nějaké bezpečné omezení (Application restrictions) jaké aplikace mohou volat API, aniž byste nepřečerpali kvótu (např. HTTP referrer).

46644179-b747-453e-a98b-f9eb48a56cac
Vygenerování klíče pro náš projekt 

Hodnotu API klíče konečně uložíme jako trvalou proměnou apiKey v našem Apps Scriptu a to v případě české lokalizace skrze hlavní menu Soubor → Vlastnosti projektu →  Vlastnosti skriptu. Odtud ji budeme načítat v kódu.

90487120-0cec-4f5e-b70d-5f64fdd2cc58
Nastavení trvalé proměnné pro projekt Apps Scriptu ve starém rozhraní editoru

Pozor, Google Apps Script používá od prosince 2020 staré a nové rozhraní editoru. V tom novém (k dubnu 2021) nelze editovat vlastnosti skriptu, a tak se musíte přepnout do staršího IDE přes tlačítko.

Tabulka Google jako databáze s výsledky

Textové titulky ve formátu srt nebudeme jazykovému API posílat přímo, ale předpřipravíme si je v tabulce, do které je nahraje funkce níže, která jako parametr používá ID souboru s titulky. 

Abychom nemuseli analyzovat titulky po větách, ale po delších celcích, provedeme tzv. bucketing. Vytvoříme shluky textu v délce dvou minut a ty se budou analyzovat jako celek. Z těchto bloků poté zjistíme, zda má část filmu spíše pozitivní, nebo naopak negativní sentiment. U dvouhodinového filmu bude podobných segmentů šedesát.

var subitlesParser = function(fileId) {
  var agregated = false;
  var CHARS = "-->";
  var BATCH_SIZE = 2; // time-window (e.g. 2minutes)
  var epoch = 0;
  var text = [];
  var output = [];
  var content = DriveApp.getFileById(fileId).getBlob().getDataAsString();
  var rows = content.split("\n");
  
  rows.forEach(function (row) {
    if (row.indexOf(CHARS) > -1) {
      var times = row.split(CHARS);
      var to = times[1].split(":");
      var hour = parseInt(to[0],10);
      var minutes = parseInt(to[1],10);
      var position = hour * 60 + minutes;
      
      if (position > BATCH_SIZE*epoch) {
         epoch++;
         var sentence = text.join("")
         sentence = sentence.replace(/\r?\n?/g,"");
         if (sentence != "") {
           var max = (BATCH_SIZE*(epoch-1));
           output.push([max, sentence]);
           text = [];
         }
      } 
      agregated = true;
    } else if (row === String.fromCharCode(13)) {
       agregated = false;
    } else if (agregated) {
      text.push(row)
    }
  });
  return output;
}

Funkce výše nám titulky načetla do tabulky a shlukla do textových řádků po 120 sekundách, které nyní konečně můžeme prohnat analýzou sentimentu.

Konečně si napíšeme funkci pro dotazování na Natural Language API od Googlu. Funkce vrátí dvě hodnoty:

  • skóre (score)
  • důležitost (magnitude)

V našem případě využijeme skóre v intervalu <-1;1>. Čím více je číslo záporné, tím negativnější emoce a naopak.

/* 
 * Get sentiment from Google Cloud Natural Language API
 */
var getSentiment = function(text) {
   var apiKey = PropertiesService.getScriptProperties().getProperty("apiKey")
   var url = "https://language.googleapis.com/v1/documents:analyzeSentiment?key=%KEY".replace("%KEY", apiKey)
   
    var data = {
       document: {
         language: "en-us",
         type: "PLAIN_TEXT",
         content: text
       },
       encodingType: 'UTF8'
     };
     
   var parameters = {
     method : 'post',
     contentType: 'application/json',
     payload : JSON.stringify(data)
   };
  
   var response = UrlFetchApp.fetch(url, parameters);
   return (response);
};

Pak zbývá už jen dopsat hlavní funkci, která vezme připravená data (dvouminutové segmenty), odešle je na API a výsledek uloží do tabulky.

var SPREADSHEET_ID = "xxxxx"; // <-- Google Spreadsheet ID

var settings = {
  nomadland : "xxxxxx" // <--- subtitles fileId 
}

function RUN() {
  var movie = "nomadland"
  var fileId = settings[movie];
  var output = subitlesParser(fileId);
  var table = [];
  table.push(["time", "score", "magnitude", "text"]);
  output.forEach(function (line) {
    var position = line[0];
    var content = line[1];
    var nlp = getSentiment(content);
    nlp = JSON.parse(nlp);
    table.push([position, nlp.documentSentiment.score, nlp.documentSentiment.magnitude, content]);
    Utilities.sleep(200);
  });

  var ss = SpreadsheetApp.openById(SPREADSHEET_ID)
  if (ss.getSheetByName(movie) === null) {
      var sheet = ss.insertSheet(movie)
  } else {
      var sheet = ss.getSheetByName(movie)
  }
  sheet.getRange(2,1,table.length,table[0].length).setValues(table);
}

5ebec54c-f116-44aa-bf49-90ea145ae98b
Pomocí jazykového API jsme doplnili k jednotlivým dvouminutovým segmentům (řádkům tabulky) sentimentální skóre, které můžeme vynést na graf

Emoce ve filmu na časové ose

Jakmile máme tabelovaná data, můžeme nad nimi v „Excelu od Googlu“ vytvořit libovolný typ graf. Vyrobíme si tedy graf emocí v čase. Hezky je na něm vidět stoupající trend pozitivních emocí během filmu (fialová čára).

0ca60000-ac59-4218-ad61-01f5359ed115
Emoce ve filmu podle API Googlu

Ve filmu jsou nejspíše tři hlavní dějové krize: 

  • okolo 20. minuty
  • okolo 76. minuty
  • okolo 100. minuty

Tedy alespoň podle API, které ohodnotilo jednotlivé pasáže anglických titulků.

Dále je zde důležitý prvek dramatu: katastrofa, ve které se radikálně změní děj. V posledních deseti minutách filmu se totiž skokově změní emoce z negativních na pozitivní a lze očekávat katarzi diváka až do konce filmu.

Dnes jsme se na několika desítkách řádků kódu v Apps Scriptu spojili s aplikačním rozhraním Googlu a ohodnotili pomocí něj anglické titulky vítězného oskarového snímku. Meze představivosti se přitom nekladou a stejně tak bychom mohli prozkoumat i něco mnohem zajímavějšího. To je už ale na vás. 

Diskuze (1) Další článek: Netac otestoval linky pro rychlé operační paměti DDR5. Hromadná výroba začne brzy

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , ,