Slik Codeer Natural Language Processing på Android Med IBM Watson

Takket være den stigende bølgen av kunstig intelligens, har brukere i disse dager kommet til å forvente apps som er både klare og klar over kontekstene de blir brukt i. IBM Watson tilbyr en rekke naturlige språkrelaterte tjenester du kan bruke til å lage slike programmer.

For eksempel kan du bruke tjenesten Natural Language Understanding til å trekke ut søkeord, enheter, følelser og mange andre semantiske detaljer fra hvilken som helst tekst brukeren leser. Og hvis teksten skjer på et fremmedspråk, kan du bruke Language Translator-tjenesten til å identifisere språket og oversette det til en bruker forstår.

I denne opplæringen skal jeg presentere deg for noen av disse tjenestene ved å vise deg hvordan du lager en app som kan oversette tyske nettsider til engelsk og trekke ut følelser, viktige enheter og følelser fra dem.

Før du fortsetter, foreslår jeg at du leser følgende innledende veiledning på IBM Watson-tjenester:

1. Aktivere tjenestene

Vi jobber med tre Watson-tjenester i dag, og hver av dem må aktiveres separat. Så åpne ditt IBM Bluemix dashboard og trykk på Skape knapp.

Den første tjenesten vi skal aktivere, er Dokumentkonvertering service, som gjør at vi kan konvertere HTML, PDF og DOCX dokumenter til vanlig tekst eller JSON. Velg den fra katalogen, gi den et meningsfylt navn, og trykk på Skape knapp.

Deretter går du tilbake til katalogen og velger Språkoversetter service. Den støtter flere allment snakket språk og kan som standard håndtere tekst i tre domener: nyheter, samtale og patent. Mens de to første domenene er tilstrekkelige for de fleste tekster, kan det siste domenet være mer nøyaktig for tekster som inneholder mange tekniske eller juridiske vilkår.

På tjenestenes konfigurasjonsside gir tjenesten et meningsfylt navn og trykker på Skape knapp.

Gå tilbake til katalogen og velg Naturlig språkforståelse service. Vi bruker denne tjenesten for å trekke ut følelser, enheter og følelser fra ustrukturert tekst. Igjen, gi det et meningsfylt navn på konfigurasjonsskjermen, og trykk på Skape knapp.

Hvis du åpner dashbordet nå, bør du kunne se noe slikt:

Alle tre tjenestene har unike påloggingsinformasjon knyttet til dem. Du må merke alle dem ned fordi du vil trenge dem senere. For å bestemme legitimasjonene til en hvilken som helst tjeneste, velg den på dashbordet, åpne dens Tjenestegodkjenninger fanen, og trykk på Se påloggingsinformasjon knapp.

2. Prosjektoppsett

For å kunne bruke disse tre tjenestene i et Android Studio-prosjekt, må vi legge til Watson Java SDK som en gjennomføring avhengighet i app modulens build.gradle fil.

implementering 'com.ibm.watson.developer_cloud: java-sdk: 3.9.1'

I tillegg bruker vi Brenselbiblioteket som en HTTP-klient, så legg det til som en gjennomføring avhengighet.

implementering 'com.github.kittinunf.fuel: fuel-android: 1.10.0'

Både drivstoff og Watson Java SDK kan fungere bare hvis vår app har INTERNETT Tillatelse, så be om det i manifestfilen.

Deretter legger du til  koder som inneholder brukernavnene og passordene til alle de tre tjenestene til strings.xml fil.

USERNAME1 password1 USERNAME2 PASSWORD2 USERNAME3 passord3

Til slutt, for å holde vår kode konsistent, i denne opplæringen bruker vi Kotlin i stedet for Java, så sørg for at du har aktivert Kotlin-støtte.

3. Bruke Document Conversion Service

Vi bruker Watson Document Conversion-tjenesten for å konvertere HTML-nettsider til vanlig tekst. For å la brukeren skrive inn en nettsideadresse, legg til en EditText widget til aktiviteten din layout. I tillegg inkluderer en TextView widget for å vise innholdet på nettsiden som vanlig tekst. For å sikre at innholdet på lange websider ikke blir avkortet, foreslår jeg at du plasserer dem i en ScrollView widget.

   

I ovennevnte kode kan du se at imeOptions attributten til EditText Widget er satt til actionGo. Det lar brukerne trykke en "Go" -knapp på sine virtuelle tastaturer når de er ferdige med å skrive adressen. For å lytte til den knappen-presse hendelsen, legg til følgende Kotlin-kode til aktiviteten din onCreate () metode:

documentURL.setOnEditorActionListener _, action, _ -> hvis (handling == EditorInfo.IME_ACTION_GO) // Mer kode her false

Inne i hendelseslytteren er det første vi må gjøre, å bestemme nettadressen som brukeren skrev inn. Vi kan gjøre det enkelt ved å få tilgang til tekst eiendom av EditText widget. Når vi har nettadressen, kan vi bruke Fuel's httpGet () Metode for å laste ned innholdet på nettsiden.

Fordi vi vil httpGet () metode for å kjøre asynkront, må vi legge til tilbakering til det ved hjelp av responseString () metode, som også tillater oss å behandle det nedlastede innholdet som en streng.

val url: String = documentURL.text.toString () url.httpGet () .responsString _, _, resultat -> val (dokument, _) = resultat hvis (err == null) // Mer kode her

Det er nå på tide å lage en forekomst av DocumentConversion klassen, som har alle metodene vi trenger for å samhandle med Document Conversion-tjenesten. Konstruktøren forventer en versionsdato sammen med tjenestens innloggingsinformasjon.

val documentConverter = DocumentConversion (DokumentConversion.VERSION_DATE_2015_12_01, resources.getString (R.string.document_conversion_username), resources.getString (R.string.document_conversion_password))

Watson Java SDK tillater ikke at vi direkte sender strenge til Document Conversion-tjenesten. Det trenger Fil objekter i stedet. Derfor, la oss nå lage en midlertidig fil ved hjelp av createTempFile () metode av Fil klasse, og skriv innholdet på nettsiden vi lastet ned til den ved hjelp av writeText () metode.

val tempFile = File.createTempFile ("temp_file", null) tempFile.writeText (dokument, Charsets.UTF_8)

På dette punktet kan vi ringe til convertDocumentToText () metode og send den midlertidige filen til den for å starte konverteringen. Metoden forventer også MIME-typen av den midlertidige filen, så ikke glem å inkludere den. Når konverteringen er fullført, kan du vise ren tekst ved å tilordne den til tekst eiendom av TextView widget.

Følgende kode viser deg hvordan du utfører konverteringen i en ny tråd og oppdaterer TextView i brukergrensesnittet:

AsyncTask.execute val plainText = documentConverter .convertDocumentToText (tempFile, "text / html") .execute () runOnUiThread documentContents.text = plainText

Du kan kjøre appen nå og skrive inn en tysk nettsidens nettadresse for å se at dokumentkonverteringstjenesten fungerer.

4. Bruke Language Translator Service

Med Language Translator-tjenesten skal vi nå konvertere ren tekst, som er på tysk, til engelsk.

I stedet for å oppdatere vårt layout, for å la brukeren manuelt starte oversettelsen, la oss legge til en meny for vår aktivitet. For å gjøre det, begynn med å opprette en ny menyen ressursfil og legg til følgende kode for det:

    

Som du kan se, oppretter koden ovenfor en meny med to alternativer: oversette og analysere. I dette trinnet jobber vi bare med det første alternativet.

For å gjøre menyen, må vi blåse den inn i onCreateOptionsMenu () metode for vår aktivitet.

overstyr moro påCreateOptionsMenu (meny: Meny?): Boolean (menyInflater.inflate (R.meny.my_menu, meny) returnere super.onCreateOptionsMenu (meny)

Ved å overstyre onOptionsItemSelected () Metode, vi kan vite når brukeren bruker menyen. Videre kan vi bestemme hvilket element brukeren trykker på ved å sjekke ITEMID. Følgende kode kontrollerer om brukeren valgte oversettelsesalternativet.

overstyr moro onOptionsItemSelected (item: MenuItem?): Boolean if (item? .emember == R.id.action_translate) // Mer kode her return true

I likhet med dokumenttjenesten har tjenesten Language Translator også en dedikert klasse som gjør at vi kan samhandle med den. Som du kanskje har gjettet, kalles det LanguageTranslator. For å opprette en forekomst av klassen må vi bare sende tjenestens innloggingsinformasjon til konstruktøren.

val translator = LanguageTranslator (resources.getString (R.string.language_translator_username), resources.getString (R.string.language_translator_password))

Klassen har en oversette() Metode vi kan nå bruke til å oversette vår tyske tekst til engelsk. Som argumenter forventer det at teksten skal oversettes som en streng, det aktuelle språket i teksten og ønsket språk.

Etter at oversettelsen er fullført, vil vi få tilgang til en TranslationResult objekt, hvis firstTranslation Egenskapen inneholder den oversatte teksten.

Følgende kode viser deg hvordan du utfører oversettelsen og gjør resultatet i TextView widget.

AsyncTask.execute val translatedDocument = translator .translate (documentContents.text .toString (), Language.GERMAN, Language.ENGLISH) .execute () runOnUiThread documentContents.text = translatedDocument .firstTranslation

Du kan nå kjøre appen igjen, skrive inn en tysk nettsideadresse, og bruk menyen til å oversette innholdet til engelsk.

5. Bruke tjenesten Natural Language Understanding

Til slutt, for å utføre en semantisk analyse på den oversatte teksten og trekke ut ulike viktige detaljer fra det, kan vi bruke NaturalLanguageUnderstanding klassen, som tjener som klient for tjenesten Natural Language Understanding.

Følgende kode viser hvordan du initialiserer klienten bare når brukeren trykker på det andre alternativet i menyen vi opprettet i forrige trinn:

if (item? .itemId == R.id.action_analyze) valanalysator = NaturalLanguageUnderstanding (NaturalLanguageUnderstanding.VERSION_DATE_2017_02_27, resources.getString (R.string.natural_language_understanding_username), resources.getString (R.string.natural_language_understanding_password)) // Mer kode her

Sammenlignet med de andre naturlige språkrelaterte tjenestene, er bruk av tjenesten Natural Language Understanding litt mer involvert, først og fremst fordi den har et stort antall funksjoner.

For nå, la oss si at vi vil bestemme den generelle følelsen av den oversatte teksten og trekke ut alle de store enhetene det nevner. Hver enkelt enhet kan ha følelser og følelser knyttet til det, så la oss si at vi også vil trekke dem ut.

For å fortelle tjenesten som vi ønsker å trekke ut alle enheter og følelsene og følelsene som er knyttet til dem, trenger vi en EntitiesOptions objekt, som kan opprettes ved hjelp av EntitiesOptions.Builder klasse.

val entityOptions = EntitiesOptions.Builder () .emotion (true) .sentiment (true) .build ()

På samme måte, for å fortelle tjenesten som vi vil ha den generelle følelsen av teksten, trenger vi en SentimentOptions gjenstand.

val sentimentOptions = SentimentOptions.Builder () .document (true) .build ()

De SentimentOptions og EntitiesOptions Objekter må nå sammenlegges for å danne en Egenskaper objekt, som kan brukes til å komponere en AnalyzeOptions gjenstand. De AnalyzeOptions objekt er det viktigste av alle de ovennevnte objektene fordi det er der du spesifiserer teksten du vil analysere.

val features = Funksjoner.Builder () .entiteter (entityOptions) .sentiment (sentimentOptions) .build () val analyzerOptions = AnalyzeOptions.Builder () .text (documentContents.text.toString ()) .features (features) .build ()

Først når AnalyzeOptions objektet er klart, vi kan passere det analysere() metode for å starte analysen.

AsyncTask.execute val results = analyzer.analyze (analyzerOptions) .execute () // Mer kode her

Resultatet av analysen er en AnalysisResults objekt, som inneholder all informasjonen vi ba om.

For å avgjøre tekstens generelle følelse må vi først trekke ut den samlede følelsespoengene ved hjelp av sentiment.document.score eiendom. En følelsespoeng er ingenting annet enn et flytende punktnummer. Hvis det er null, er følelsen nøytral. Hvis det er negativt eller positivt, er følelsen også negativ eller positiv.

val overallSentimentScore = results.sentiment.document.score var overallSentiment = "Positive" hvis (overallSentimentScore < 0.0) overallSentiment = "Negative" if(overallSentimentScore == 0.0) overallSentiment = "Neutral" var output = "Overall sentiment: $overallSentiment\n\n"

Deretter ved å løpe gjennom enheter liste tilstede i AnalysisResults objekt, vi kan behandle hver enhet individuelt. Som standard har hver enhet en type tilknyttet den. Tjenesten kan for eksempel fortelle om et foretak er en person, et selskap eller et kjøretøy. For tiden kan den identifisere over 450 forskjellige typer enheter.

Fordi vi ba om dem, vil hver enhet nå også få en følelsespoeng og følelser knyttet til den.

Vi kan bestemme følelsespoengene ved å bare bruke sentiment.score eiendom. Det er imidlertid ikke like greit å bestemme følelser knyttet til en enhet. Watson støtter fem følelser for øyeblikket: sinne, glede, avsky, frykt og tristhet. Hver enhet vil ha alle de fem følelsene, men forskjellige verdier knyttet til hver av dem, og angi hvor trygg tjenesten er at følelsen er riktig. Derfor, for å bestemme riktig følelse, må vi velge den som har den høyeste verdien.

Følgende kode viser hver enhet sammen med sin type, følelsespoeng og følelser:

for (enhet i results.entities) output + = "$ entity.text ($ entity.type) \ n" val validEmotions = arrayOf ("Anger", "Joy", "Disgust", "Fear" , "Tristhet") val emotionValues ​​= arrayOf (entity.emotion.anger, entity.emotion.joy, entity.emotion.disgust, entity.emotion.fear, entity.emotion.sadness) val currentEmotion = validEmotions [emotionValues.indexOf (emotionValues .max ())] output + = "Følelse: $ currentEmotion," + "Sentiment: $ entity.sentiment.score" + "\ n \ n"

For å vise produksjonen vi genererte, kan vi igjen oppdatere TextView widget.

runOnUiThread documentContents.text = output

På dette tidspunktet kan du kjøre appen igjen for å se alle de tre tjenestene som fungerer sammen.

Konklusjon

Du vet nå hvordan du bruker tre av de mest brukte naturlige språkrelaterte tjenestene Watson tilbyr. I denne opplæringen så du også hvor lett det er å bruke Watson Java SDK for å få alle tjenestene til å fungere sammen for å lage en smart Android-app.

For å lære mer om tjenestene og SDK, kan du se på SDKs GitHub-depot. Og for å lære mer om bruk av Watson maskinlæring i dine egne apper, sjekk ut noen av våre andre innlegg her på Envato Tuts+!