So codieren Sie die Verarbeitung natürlicher Sprache auf Android mit IBM Watson
German (Deutsch) translation by Tatsiana Bochkareva (you can also view the original English article)
Dank der steigenden Welle der künstlichen Intelligenz erwarten Nutzer heutzutage Apps, die sowohl intelligent als auch kontextbewusst sind. IBM Watson bietet eine Vielzahl von Services im Zusammenhang mit natürlicher Sprache, mit denen Sie solche Apps erstellen können.
Sie können beispielsweise seinen Natural Language Understanding-Dienst verwenden, um Schlüsselwörter, Entitäten, Stimmungen und viele andere semantische Details aus jedem Text zu extrahieren, den der Benutzer liest. Und wenn der Text in einer Fremdsprache ist, können Sie den Language Translator-Dienst verwenden, um die Sprache zu identifizieren und in eine für den Benutzer verständliche Sprache zu übersetzen.
In diesem Tutorial stelle ich Ihnen einige dieser Dienste vor, indem ich Ihnen zeige, wie Sie eine App erstellen, die deutsche Webseiten ins Englische übersetzen und Gefühle, wichtige Entitäten und Emotionen daraus extrahieren kann.
Bevor Sie fortfahren, empfehle ich Ihnen, das folgende einführende Tutorial zu IBM Watson-Services zu lesen:
1. Aktivierung der Dienste
Wir arbeiten heute mit drei Watson-Diensten, und jeder von ihnen muss separat aktiviert werden. Öffnen Sie also Ihr IBM Bluemix-Dashboard und klicken Sie auf die Schaltfläche Erstellen.
Der erste Dienst, den wir aktivieren werden, ist der Dokumentkonvertierungsdienst, mit dem wir HTML-, PDF- und DOCX-Dokumente in Nur-Text- oder JSON-Dateien konvertieren können. Wählen Sie es aus dem Katalog aus, geben Sie ihm einen aussagekräftigen Namen und klicken Sie auf die Schaltfläche Erstellen.



Gehen Sie als Nächstes zurück zum Katalog und wählen Sie den Service Language Translator. Es unterstützt mehrere weit verbreitete Sprachen und kann standardmäßig Text in drei Bereichen verarbeiten: Nachrichten, Konversation und Patent. Während die ersten beiden Domänen für die meisten Texte ausreichend sind, kann die letzte Domäne für Texte mit vielen technischen oder juristischen Begriffen genauer sein.
Geben Sie dem Dienst auf seiner Konfigurationsseite einen aussagekräftigen Namen und klicken Sie auf die Schaltfläche Erstellen.



Kehren Sie zum Katalog zurück und wählen Sie den Service Natural Language Understanding. Wir verwenden diesen Dienst, um Gefühle, Entitäten und Emotionen aus unstrukturiertem Text zu extrahieren. Geben Sie ihm im Konfigurationsbildschirm erneut einen aussagekräftigen Namen und klicken Sie auf die Schaltfläche Erstellen.



Wenn Sie jetzt das Dashboard öffnen, sollten Sie in der Lage sein, etwa Folgendes zu sehen:



Allen drei Diensten sind eindeutige Anmeldeinformationen zugeordnet. Sie müssen sie alle notieren, da Sie sie später brauchen werden. Um die Anmeldeinformationen eines Dienstes zu ermitteln, wählen Sie ihn im Dashboard aus, öffnen Sie die Registerkarte Dienstanmeldeinformationen und klicken Sie auf die Schaltfläche Anmeldeinformationen anzeigen.
2. Projekteinrichtung
Um diese drei Dienste in einem Android Studio-Projekt verwenden zu können, müssen wir das Watson Java SDK als implementation
-Abhängigkeit in der Datei build.gradle des app
-Moduls hinzufügen.
implementation 'com.ibm.watson.developer_cloud:java-sdk:3.9.1'
Darüber hinaus verwenden wir die Fuel-Bibliothek als HTTP-Client, fügen Sie sie also auch als implementation
-Abhängigkeit hinzu.
implementation 'com.github.kittinunf.fuel:fuel-android:1.10.0'
Sowohl Fuel als auch das Watson Java SDK können nur funktionieren, wenn unsere App über die INTERNET
-Berechtigung verfügt. Fragen Sie daher in der Manifestdatei danach.
<uses-permission android:name="android.permission.INTERNET"/>
Fügen Sie als Nächstes <string>
-Tags hinzu, die die Benutzernamen und Kennwörter aller drei Dienste zur Datei strings.xml enthalten.
<string name="document_conversion_username">USERNAME1</string> <string name="document_conversion_password">PASSWORD1</string> <string name="language_translator_username">USERNAME2</string> <string name="language_translator_password">PASSWORD2</string> <string name="natural_language_understanding_username">USERNAME3</string> <string name="natural_language_understanding_password">PASSWORD3</string>
Um unseren Code prägnant zu halten, verwenden wir in diesem Tutorial Kotlin anstelle von Java. Stellen Sie also sicher, dass Sie die Kotlin-Unterstützung aktiviert haben.
3. Verwenden des Dokumentenkonvertierungsdienstes
Wir verwenden den Watson Document Conversion-Dienst, um HTML-Webseiten in Nur-Text zu konvertieren. Damit der Benutzer eine Webseitenadresse eingeben kann, fügen Sie dem Layout Ihrer Aktivität ein EditText
-Widget hinzu. Fügen Sie außerdem ein TextView
-Widget hinzu, um den Inhalt der Webseite als Nur-Text anzuzeigen. Um sicherzustellen, dass der Inhalt langer Webseiten nicht abgeschnitten wird, schlage ich vor, dass Sie sie in einem ScrollView
-Widget platzieren.
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/documentURL" android:inputType="textUri" android:hint="URL" android:imeOptions="actionGo" /> <ScrollView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_below="@+id/documentURL"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/documentContents" /> </ScrollView>
Im obigen Code sehen Sie, dass das imeOptions
-Attribut des EditText
-Widgets auf actionGo
gesetzt ist. Es ermöglicht Benutzern, eine "Go"-Taste auf ihren virtuellen Tastaturen zu drücken, wenn sie mit der Eingabe der Adresse fertig sind. Um dieses Tastendruckereignis abzuhören, fügen Sie den folgenden Kotlin-Code zur onCreate()
-Methode Ihrer Aktivität hinzu:
documentURL.setOnEditorActionListener { _, action, _ -> if (action == EditorInfo.IME_ACTION_GO) { // More code here } false }
Innerhalb des Ereignis-Listeners müssen wir zunächst die URL ermitteln, die der Benutzer eingegeben hat. Wir können dies ganz einfach tun, indem wir auf die text
-Eigenschaft des EditText
-Widgets zugreifen. Sobald wir die URL haben, können wir die httpGet()
-Methode von Fuel verwenden, um den Inhalt der Webseite herunterzuladen.
Da die Methode httpGet()
asynchron ausgeführt werden soll, müssen wir ihr mithilfe der Methode responseString()
einen Rückruf hinzufügen, der es uns auch ermöglicht, den heruntergeladenen Inhalt als String zu verarbeiten.
val url:String = documentURL.text.toString() url.httpGet().responseString { _, _, result -> val (document, _) = result if (err == null) { // More code here } }
Jetzt ist es an der Zeit, eine Instanz der DocumentConversion
-Klasse zu erstellen, die über alle Methoden verfügt, die wir für die Interaktion mit dem Document Conversion-Dienst benötigen. Sein Konstruktor erwartet ein Versionsdatum zusammen mit den Anmeldeinformationen des Dienstes.
val documentConverter = DocumentConversion( DocumentConversion.VERSION_DATE_2015_12_01, resources.getString(R.string.document_conversion_username), resources.getString(R.string.document_conversion_password) )
Das Watson Java SDK erlaubt es uns nicht, Zeichenfolgen direkt an den Dokumentkonvertierungsdienst zu übergeben. Es benötigt stattdessen File
-Objekte. Lassen Sie uns daher nun eine temporäre Datei mit der Methode createTempFile()
der Klasse File
erstellen und den Inhalt der heruntergeladenen Webseite mit der Methode writeText()
darauf schreiben.
val tempFile = File.createTempFile("temp_file", null) tempFile.writeText(document, Charsets.UTF_8)
An dieser Stelle können wir die Methode convertDocumentToText()
aufrufen und ihr die temporäre Datei übergeben, um die Konvertierung zu starten. Die Methode erwartet auch den MIME-Typ der temporären Datei, also vergessen Sie nicht, ihn einzufügen. Sobald die Konvertierung abgeschlossen ist, können Sie den Klartext anzeigen, indem Sie ihn einfach der text
-Eigenschaft des TextView
-Widgets zuweisen.
Der folgende Code zeigt Ihnen, wie Sie die Konvertierung in einem neuen Thread durchführen und die TextView
im UI-Thread aktualisieren:
AsyncTask.execute { val plainText = documentConverter .convertDocumentToText(tempFile, "text/html") .execute() runOnUiThread { documentContents.text = plainText } }
Sie können die App jetzt ausführen und die URL einer deutschen Webseite eingeben, um zu sehen, wie der Dokumentkonvertierungsdienst funktioniert.



4. Verwenden des Sprachübersetzerdienstes
Mit dem Service Language Translator werden wir nun den Klartext, der in Deutsch ist, ins Englische umwandeln.
Anstatt unser Layout zu aktualisieren, damit der Benutzer die Übersetzung manuell starten kann, fügen wir unserer Aktivität ein Menü hinzu. Erstellen Sie dazu zunächst eine neue Menüressourcendatei und fügen Sie den folgenden Code hinzu:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_translate" android:title="Translate" app:showAsAction = "never" /> <item android:id="@+id/action_analyze" android:title="Analyze" app:showAsAction = "never" /> </menu>
Wie Sie sehen, erstellt der obige Code ein Menü mit zwei Optionen: Übersetzen und Analysieren. In diesem Schritt arbeiten wir nur mit der ersten Option.
Um das Menü zu rendern, müssen wir es innerhalb der Methode onCreateOptionsMenu()
unserer Aktivität aufblasen.
override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.my_menu, menu) return super.onCreateOptionsMenu(menu) }
Durch Überschreiben der Methode onOptionsItemSelected()
können wir wissen, wann der Benutzer das Menü verwendet. Darüber hinaus können wir anhand der itemId
feststellen, welches Element der Benutzer gedrückt hat. Der folgende Code überprüft, ob der Benutzer die Übersetzungsoption ausgewählt hat.
override fun onOptionsItemSelected(item: MenuItem?): Boolean { if(item?.itemId == R.id.action_translate) { // More code here } return true }
Genau wie der Document Service verfügt auch der Language Translator Service über eine eigene Klasse, die es uns ermöglicht, mit ihm zu interagieren. Wie Sie vielleicht erraten haben, heißt es LanguageTranslator
. Um eine Instanz der Klasse zu erstellen, müssen wir nur die Anmeldeinformationen des Dienstes an seinen Konstruktor übergeben.
val translator = LanguageTranslator( resources.getString(R.string.language_translator_username), resources.getString(R.string.language_translator_password) )
Die Klasse hat eine translate()
-Methode, mit der wir nun unseren deutschen Text ins Englische übersetzen können. Als Argumente erwartet es, dass der Text als Zeichenfolge übersetzt wird, die aktuelle Sprache des Textes und die gewünschte Sprache.
Nachdem die Übersetzung erfolgreich abgeschlossen wurde, haben wir Zugriff auf ein TranslationResult
-Objekt, dessen firstTranslation
-Eigenschaft den übersetzten Text enthält.
Der folgende Code zeigt Ihnen, wie Sie die Übersetzung durchführen und das Ergebnis im TextView
-Widget rendern.
AsyncTask.execute { val translatedDocument = translator .translate( documentContents.text .toString(), Language.GERMAN, Language.ENGLISH ).execute() runOnUiThread { documentContents.text = translatedDocument .firstTranslation } }
Sie können die App jetzt erneut ausführen, die URL einer deutschen Webseite eingeben und den Inhalt über das Menü ins Englische übersetzen.



5. Verwenden des Dienstes zum Verständnis natürlicher Sprache
Um schließlich eine semantische Analyse des übersetzten Textes durchzuführen und verschiedene wichtige Details daraus zu extrahieren, können wir die NaturalLanguageUnderstanding
-Klasse verwenden, die als Client für den Natural Language Understanding-Dienst dient.
Der folgende Code zeigt Ihnen, wie Sie den Client nur initialisieren, wenn der Benutzer die zweite Option des im vorherigen Schritt erstellten Menüs drückt:
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) ) // More code here }
Im Vergleich zu den anderen auf natürliche Sprache bezogenen Diensten ist die Verwendung des Dienstes Natural Language Understanding etwas aufwendiger, vor allem weil er eine große Anzahl von Funktionen bietet.
Nehmen wir vorerst an, wir möchten die Gesamtstimmung des übersetzten Textes bestimmen und alle darin erwähnten Hauptentitäten extrahieren. Jeder Entität selbst kann eine Emotion und ein Gefühl zugeordnet sein, also sagen wir, wir möchten auch diese extrahieren.
Um dem Dienst mitzuteilen, dass wir alle Entitäten und die damit verbundenen Emotionen und Stimmungen extrahieren möchten, benötigen wir ein EntitiesOptions
-Objekt, das mit der EntitiesOptions.Builder
-Klasse erstellt werden kann.
val entityOptions = EntitiesOptions.Builder() .emotion(true) .sentiment(true) .build()
Ebenso benötigen wir ein SentimentOptions
-Objekt, um dem Dienst mitzuteilen, dass wir die Gesamtstimmung des Textes haben möchten.
val sentimentOptions = SentimentOptions.Builder() .document(true) .build()
Die Objekte SentimentOptions
und EntitiesOptions
müssen nun zu einem Features
-Objekt gebündelt werden, das zum Erstellen eines AnalyzeOptions
-Objekts verwendet werden kann. Das AnalyzeOptions
-Objekt ist das wichtigste aller oben genannten Objekte, da Sie dort den zu analysierenden Text angeben.
val features = Features.Builder() .entities(entityOptions) .sentiment(sentimentOptions) .build() val analyzerOptions = AnalyzeOptions.Builder() .text(documentContents.text.toString()) .features(features) .build()
Sobald das AnalyzeOptions
-Objekt bereit ist, können wir ihm die Methode analyze()
übergeben, um die Analyse zu starten.
AsyncTask.execute { val results = analyzer.analyze(analyzerOptions).execute() // More code here }
Das Ergebnis der Analyse ist ein AnalysisResults
-Objekt, das alle von uns abgefragten Informationen enthält.
Um die Gesamtstimmung des Textes zu bestimmen, müssen wir zuerst die Gesamtstimmungsbewertung mithilfe der sentiment.document.score
-Eigenschaft extrahieren. Ein Sentiment-Score ist nichts anderes als eine Gleitkommazahl. Wenn es null ist, ist das Sentiment neutral. Wenn es negativ oder positiv ist, ist auch die Stimmung negativ oder positiv.
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"
Als nächstes können wir jede entities
einzeln verarbeiten, indem wir die im AnalysisResults
-Objekt vorhandene Entitätenliste durchlaufen. Standardmäßig ist jeder Entität ein Typ zugeordnet. Der Dienst kann beispielsweise erkennen, ob es sich bei einer Entität um eine Person, ein Unternehmen oder ein Fahrzeug handelt. Derzeit kann es über 450 verschiedene Arten von Entitäten identifizieren.
Da wir danach gefragt haben, hat jede Entität jetzt auch einen Sentiment-Score und damit verbundene Emotionen.
Wir können den Sentiment-Score bestimmen, indem wir einfach die sentiment.score
-Eigenschaft verwenden. Die Bestimmung der mit einer Entität verbundenen Emotion ist jedoch nicht so einfach. Watson unterstützt derzeit fünf Emotionen: Wut, Freude, Ekel, Angst und Traurigkeit. Jede Entität wird alle fünf Emotionen haben, aber mit jeder von ihnen unterschiedliche Werte, die angeben, wie sicher der Service ist, dass die Emotion richtig ist. Um die richtige Emotion zu bestimmen, müssen wir daher diejenige mit dem höchsten Wert auswählen.
Der folgende Code listet jede Entität zusammen mit ihrem Typ, Sentiment-Score und Emotion auf:
for(entity in results.entities) { output += "${entity.text} (${entity.type})\n" val validEmotions = arrayOf("Anger", "Joy", "Disgust", "Fear", "Sadness") 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 += "Emotion: ${currentEmotion}, " + "Sentiment: ${entity.sentiment.score}" + "\n\n" }
Um die von uns generierte Ausgabe anzuzeigen, können wir das TextView
-Widget erneut aktualisieren.
runOnUiThread { documentContents.text = output }
An diesem Punkt können Sie die App erneut ausführen, um zu sehen, wie alle drei Dienste zusammenarbeiten.



Abschluss
Sie wissen jetzt, wie Sie drei der am häufigsten verwendeten Dienste im Zusammenhang mit natürlicher Sprache nutzen, die Watson anbietet. In diesem Tutorial haben Sie auch gesehen, wie einfach es ist, das Watson Java SDK zu verwenden, damit alle Dienste zusammenarbeiten, um eine intelligente Android-App zu erstellen.
Weitere Informationen zu den Diensten und dem SDK finden Sie im GitHub-Repository des SDK. Und um mehr über die Verwendung von Watson Machine Learning in Ihren eigenen Apps zu erfahren, lesen Sie einige unserer anderen Beiträge hier auf Envato Tuts+!
- Android SDKSo verwenden Sie Google Cloud Machine Learning Services für AndroidAshraff Hathibelagal
- Android-DingeAndroid-Dinge und maschinelles LernenPaul Trebilcox-Ruiz
- Android SDKEinführung in Android-ArchitekturkomponentenTin Megali
- Maschinelles LernenCodieren einer Android-App mit IBM Watson Machine LearningAshraff Hathibelagal
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weekly