Hoe natuurlijke taalverwerking op Android te coderen met IBM Watson

Dankzij de stijgende golf van kunstmatige intelligentie, verwachten gebruikers tegenwoordig apps die zowel slim zijn als zich bewust zijn van de contexten waarin ze worden gebruikt. IBM Watson biedt een verscheidenheid aan natuurlijke taalgerelateerde services die u kunt gebruiken om dergelijke apps te maken.

U kunt bijvoorbeeld de Natural Language Understanding-service gebruiken om sleutelwoorden, entiteiten, sentimenten en veel andere semantische details te extraheren uit elke tekst die de gebruiker leest. En als de tekst toevallig in een vreemde taal is, kunt u de Language Translator-service gebruiken om de taal te identificeren en te vertalen naar een taal die de gebruiker begrijpt.

In deze zelfstudie laat ik je kennismaken met een aantal van deze services door je te laten zien hoe je een app kunt maken die Duitse webpagina's naar het Engels vertaalt en gevoelens, belangrijke entiteiten en emoties daaruit haalt.

Voordat u verdergaat, raad ik u aan de volgende introductietutorial over IBM Watson-services te lezen:

1. De services activeren

We werken vandaag met drie Watson-services en deze moeten afzonderlijk worden geactiveerd. Open dus uw IBM Bluemix-dashboard en druk op creëren knop.

De eerste service die we gaan activeren is de Documentconversie service, waarmee we HTML-, PDF- en DOCX-documenten kunnen converteren naar platte tekst of JSON. Selecteer het uit de catalogus, geef het een betekenisvolle naam en druk op de creëren knop.

Ga vervolgens terug naar de catalogus en kies de Vertaler service. Het ondersteunt verschillende veel gesproken talen en kan standaard tekst verwerken in drie domeinen: nieuws, conversatie en patent. Hoewel de eerste twee domeinen geschikt zijn voor de meeste teksten, kan het laatste domein nauwkeuriger zijn voor teksten met veel technische of juridische termen.

Geef de service op de configuratiepagina een betekenisvolle naam en druk op de creëren knop.

Keer terug naar de catalogus en kies de Natuurlijk taalbegrip service. We zullen deze service gebruiken om gevoelens, entiteiten en emoties uit ongestructureerde tekst te halen. Nogmaals, geef het een betekenisvolle naam in het configuratiescherm en druk op de creëren knop.

Als je nu het dashboard opent, zou je zoiets als dit kunnen zien:

Alle drie de services hebben unieke inloggegevens die aan hen zijn gekoppeld. Je moet ze allemaal opschrijven omdat je ze later nodig hebt. Om de inloggegevens van een dienst te bepalen, selecteert u deze op het dashboard, opent u het Serviceformulieren tab en druk op de Bekijk legitimatiegegevens knop.

2. Projectinstellingen

Om deze drie services te kunnen gebruiken in een Android Studio-project, moeten we de Watson Java SDK toevoegen als een implementatie afhankelijkheid in de app module build.gradle het dossier.

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

Daarnaast zullen we de Fuel-bibliotheek gebruiken als een HTTP-client, dus voeg deze ook toe als een implementatie afhankelijkheid.

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

Zowel Fuel als de Watson Java SDK kunnen alleen werken als onze app de INTERNET toestemming, dus vraag ernaar in het manifestbestand.

Voeg vervolgens toe  tags met de gebruikersnamen en wachtwoorden van alle drie services voor de strings.xml het dossier.

USERNAME1 password1 USERNAME2 password2 USERNAME3 wachtwoord3

Ten slotte, om onze code beknopt te houden, gebruiken we in deze tutorial Kotlin in plaats van Java, dus zorg ervoor dat je Kotlin-ondersteuning hebt ingeschakeld.

3. Gebruik van de Document Conversion Service

We zullen de Watson Document Conversion-service gebruiken om HTML-webpagina's naar onbewerkte tekst te converteren. Om de gebruiker toe te laten een webpagina-adres in te typen, voegt u een toe Tekst bewerken widget naar de lay-out van uw activiteit. Voeg daarnaast een Tekstweergave widget om de inhoud van de webpagina weer te geven als platte tekst. Om ervoor te zorgen dat de inhoud van lange webpagina's niet wordt afgekapt, raad ik aan deze in een map te plaatsen ScrollView widget.

   

In de bovenstaande code kunt u zien dat de imeOptions attribuut van de Tekst bewerken widget is ingesteld op actionGo. Hiermee kunnen gebruikers op hun virtuele toetsenborden op de knop "Go" drukken wanneer ze het adres hebben getypt. Als u naar die knop-druk-gebeurtenis wilt luisteren, voegt u de volgende Kotlin-code toe aan de activiteiten van uw activiteit onCreate () methode:

documentURL.setOnEditorActionListener _, action, _ -> if (action == EditorInfo.IME_ACTION_GO) // Meer code hier false

In de luisteraar van het evenement is het eerste dat we moeten doen, de URL bepalen die de gebruiker heeft getypt. We kunnen dit eenvoudig doen door toegang te krijgen tot de tekst eigendom van de Tekst bewerken widget. Zodra we de URL hebben, kunnen we Fuel's gebruiken httpGet () methode om de inhoud van de webpagina te downloaden.

Omdat we het willen httpGet () methode om asynchroon te draaien, moeten we een callback toevoegen met behulp van de responseString () methode, die ons ook in staat stelt om de gedownloade inhoud als een string te verwerken.

val url: String = documentURL.text.toString () url.httpGet (). responseString _, _, result -> val (document, _) = result if (err == null) // Meer code hier

Het is nu tijd om een ​​instantie van de te maken DocumentConversion klasse, die alle methoden heeft die we nodig hebben om te communiceren met de Document Conversion-service. De constructor verwacht een versiedatum samen met de inloggegevens van de service.

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

De Watson Java SDK staat ons niet toe om strings rechtstreeks door te geven aan de Document Conversion-service. Het heeft nodig het dossier objecten in plaats daarvan. Laten we daarom nu een tijdelijk bestand maken met behulp van de createTempFile () methode van de het dossier klasse en schrijf de inhoud van de webpagina die we hebben gedownload met behulp van de WRITETEXT () methode.

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

Op dit punt kunnen we de convertDocumentToText () methode en geef het tijdelijke bestand door om de conversie te starten. De methode verwacht ook het MIME-type van het tijdelijke bestand, dus vergeet niet om het op te nemen. Zodra de conversie is voltooid, kunt u de onbewerkte tekst weergeven door deze eenvoudigweg toe te wijzen aan de tekst eigendom van de Tekstweergave widget.

De volgende code laat zien hoe u de conversie in een nieuwe thread uitvoert en de Tekstweergave in de UI-thread:

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

U kunt de app nu uitvoeren en de URL van een Duitse webpagina invoeren om de Document Conversion-service te gebruiken.

4. Gebruik van de Language Translator-service

Met de Language Translator-service converteren we nu de gewone tekst, die in het Duits is, in het Engels.

In plaats van onze lay-out bij te werken, zodat de gebruiker de vertaling handmatig kan starten, kunnen we een menu toevoegen aan onze activiteit. Hiertoe maakt u eerst een nieuw menubronbestand en voegt u de volgende code toe:

    

Zoals je ziet, creëert de bovenstaande code een menu met twee opties: vertalen en analyseren. In deze stap werken we alleen met de eerste optie.

Om het menu weer te geven, moeten we het binnen de onCreateOptionsMenu () methode van onze activiteit.

override fun onCreateOptionsMenu (menu: Menu?): Boolean menuInflater.inflate (R.menu.my_menu, menu) return super.onCreateOptionsMenu (menu)

Door de onOptionsItemSelected () methode, kunnen we weten wanneer de gebruiker het menu gebruikt. Bovendien kunnen we bepalen welk item de gebruiker heeft ingedrukt door de item ID. De volgende code controleert of de gebruiker de vertaaloptie heeft gekozen.

override fun onOptionsItemSelected (item: MenuItem?): Boolean if (item? .itemId == R.id.action_translate) // Meer code hier return true

Net als de documentservice heeft ook de Language Translator-service een speciale klasse waarmee we ermee kunnen communiceren. Zoals je misschien al geraden hebt, is het genoemd Vertaler. Om een ​​instantie van de klasse te maken, moeten we alleen de aanmeldingsreferenties van de service doorgeven aan de constructor.

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

De klas heeft een vertalen() methode die we nu kunnen gebruiken om onze Duitse tekst naar het Engels te vertalen. Als zijn argumenten verwacht hij dat de tekst vertaalt als een tekenreeks, de huidige taal van de tekst en de gewenste taal.

Nadat de vertaling is voltooid, hebben we toegang tot een TranslationResult object, waarvan firstTranslation eigenschap bevat de vertaalde tekst.

De volgende code laat zien hoe u de vertaling uitvoert en het resultaat in de Tekstweergave widget.

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

U kunt de app nu opnieuw uitvoeren, de URL van een Duitse webpagina invoeren en het menu gebruiken om de inhoud naar het Engels te vertalen.

5. Gebruik maken van de Natural Language Understanding Service

Als laatste, om een ​​semantische analyse van de vertaalde tekst uit te voeren en er verschillende belangrijke details uit te extraheren, kunnen we de NaturalLanguageUnderstanding klasse, die als cliënt dient voor de Natural Language Understanding-service.

De volgende code toont u hoe u de client alleen kunt initialiseren wanneer de gebruiker op de tweede optie van het menu drukt dat we in de vorige stap hebben gemaakt:

if (item? .itemId == R.id.action_analyze) val analyzer = NaturalLanguageUnderstanding (NaturalLanguageUnderstanding.VERSION_DATE_2017_02_27, resources.getString (R.string.natural_language_understanding_username), resources.getString (R.string.natural_language_understanding_password)) // Meer code hier

In vergelijking met de andere natuurlijke taalgerelateerde diensten is het gebruik van de Natural Language Understanding-service iets meer betrokken, vooral omdat het een groot aantal functies heeft.

Laten we voor nu zeggen dat we het algemene sentiment van de vertaalde tekst willen bepalen en alle belangrijke entiteiten die het vermeldt, extraheren. Elke entiteit zelf kan er een emotie en sentiment aan koppelen, dus laten we zeggen dat we die ook willen extraheren.

Om de dienst te vertellen dat we alle entiteiten en de emoties en gevoelens die eraan verbonden zijn, willen extraheren, hebben we een EntitiesOptions object, dat kan worden gemaakt met behulp van de EntitiesOptions.Builder klasse.

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

Evenzo, om de dienst te vertellen dat we het algemene sentiment van de tekst willen, hebben we een SentimentOptions voorwerp.

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

De SentimentOptions en EntitiesOptions objecten moeten nu samen worden gebundeld om een ​​te vormen Kenmerken object, dat kan worden gebruikt om een ​​samen te stellen AnalyzeOptions voorwerp. De AnalyzeOptions object is het belangrijkste van alle bovenstaande objecten, omdat u hier de tekst opgeeft die u wilt analyseren.

val features = Features.Builder () .entities (entityOptions) .sentiment (sentimentOptions) .build () val analyzerOptions = AnalyseOpties.Builder () .text (documentContents.text.toString ()) .features (features) .build ()

Zodra de AnalyzeOptions object is klaar, we kunnen het doorgeven analyseren() methode om de analyse te starten.

AsyncTask.execute val results = analyzer.analyze (analyzerOptions) .execute () // Hier meer code

Het resultaat van de analyse is een Analyse resultaten object, met alle informatie waar we om vroegen.

Om het algemene sentiment van de tekst te bepalen, moeten we eerst de algemene sentimentscore extraheren met behulp van de sentiment.document.score eigendom. Een sentimentscore is niets anders dan een drijvende-kommawaarde. Als het nul is, is het sentiment neutraal. Als het negatief of positief is, is het sentiment ook negatief of positief.

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

Vervolgens door door de entiteiten lijst aanwezig in de Analyse resultaten object, kunnen we elke entiteit afzonderlijk verwerken. Standaard heeft elke entiteit een type dat eraan is gekoppeld. De service kan bijvoorbeeld bepalen of een entiteit een persoon, een bedrijf of een voertuig is. Momenteel kan het meer dan 450 verschillende soorten entiteiten identificeren.

Omdat we ernaar hebben gevraagd, heeft elke entiteit nu ook een sentimentscore en bijbehorende emoties.

We kunnen de sentimentscore bepalen door simpelweg de. Te gebruiken sentiment.score eigendom. Het bepalen van de emotie verbonden aan een entiteit is echter niet zo eenvoudig. Watson ondersteunt momenteel vijf emoties: woede, vreugde, afkeer, angst en verdriet. Elke entiteit heeft alle vijf emoties, maar er zijn verschillende waarden verbonden aan elk van deze entiteiten, en geeft aan hoe betrouwbaar de service is dat de emotie correct is. Daarom, om de juiste emotie te bepalen, moeten we degene kiezen met de hoogste waarde.

De volgende code vermeldt elke entiteit, samen met het type, de sentimentscore en emotie:

for (entity in results.entities) output + = "$ entity.text ($ entity.type) \ n" val validEmotions = arrayOf ("Anger", "Joy", "Disgust", "Fear" , "Verdriet") 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 + = "Emotie: $ currentEmotion," + "Sentiment: $ entity.sentiment.score" + "\ n \ n"

Om de output die we hebben gegenereerd weer te geven, kunnen we de Tekstweergave widget.

runOnUiThread documentContents.text = output

Op dit punt kunt u de app opnieuw uitvoeren om alle drie services samen te laten werken.

Conclusie

U weet nu hoe u drie van de meest gebruikte natuurlijke taalgerelateerde services die Watson biedt, kunt gebruiken. In deze zelfstudie zag je ook hoe eenvoudig het is om de Watson Java SDK te gebruiken om alle services samen te laten werken om een ​​slimme Android-app te maken.

Voor meer informatie over de services en de SDK kunt u verwijzen naar de GitHub-opslagplaats van de SDK. En voor meer informatie over het gebruik van Watson-machine leren in uw eigen apps, bekijk een aantal van onze andere berichten hier op Envato Tuts+!