Data Science, Machine Learning und KI
Kontakt

Introduction

Teaching machines to handle image data is probably one of the most exciting tasks in our daily routine at STATWORX. Computer vision in general is a path to many possibilities some would consider intruiging. Besides learning images, computer vision algorithms also enable machines to learn any kind of video sequenced data. With autonomous driving on the line, learning images and videos is probably one of hottest topics right.

learning images - so hot right now

In this post, I will show you how to get started with learning image data. I will make use of Keras, a high level API for Tensorflow, CTNK, and Theano. Keras is implemented in Python and in R. For this post I will work through the Python implementation.

Setup

I am using Python 3.6.5. and Keras is running with a Tensorflow backend. The dataset I will be using is the Airbus Ship Detection dataset from their recent Kaggle Competition. To get started, we will be building a very simple network, a so called autoencoder network. Autoencoders are simple networks in the sense that they are not aiming to predict any target. They rather aim to learn and reconstruct images or data in general. In his blog post Venelin Valkov shows the following figure, I think is quite cool:

mushroom encoder

The figure perfectly describes the intension of an autoencoder. The algorithm takes an input, compresses, and then tries to reconstruct it. Why would we do this? Well, autoencoders have numerous interesting applications. First, they are reasonably good in detecting outliers. The idea is, you teach a machine to reconstruct non-outliers. Thus, when confronted with an outlier, the algorithm will probably have a hard time reconstructing that very observation. Second, autoencoders are fairly interesting to look at, when you are looking to reduce the dimensionality of your data. Speaking about images, you can think of it as a complexity reduction for the images. An algorithm is unlikely to reconstruct nuances of the image that are rather irrelevant to the content. Image recognition or classification algorithms are prone to overreact to certain nuances of images, so denoising them, might ease the learning procedure. Thus, autoencoders can serve as a powerful preprocessing tool to denoising your data.

Data Preparation

Prepararing your data is one of the most important tasks when training algorithms. Even more so, when you are handling image data. Images typically require large amounts of storage, especially since computer vision algorithms usually need to be fed with a considerable amount of data. To encompass this issue my colleauges and I typically make use of either large on-premise servers or cloud instances.

For this blog post however, I am choosing to run everything on my local machine. Why? Well, if you are reading this and you are interested in taking your first steps in developing your own code to handle image data, I would probably bother you with details of setting up cloud instances. If you are reading this and you are already experienced in working with this kind of problems, you will most likely work with cloud instances and you will be bothered by my description as well. So, for this little experiment I am running everything on my local machine and I organized the data as follows:


00_data
    |
    | train
	| train_image_01
	| train_image_02
	| ...
    | test
	| test_image_01
	| ...

To read in the data, I am simply looping over the images. I am using the OpenCV implementation cv2 and the Keras preprocessing tools. I know, I know Keras has this genious ImageDataGenerator modul, however I think it is kind of important to understand the required input, so for this post I will make use of the OpenCV tools. The preprocessing is a little different than with other data. While we see something similar to this:

training images

A machine however, does not see images, but rather data. Each image is representated by a matrix of pixel values. Thus each picture is a data matrix. Unlike with other problems where all data is compressed in one matrix, we need to consider this complex setup. To deal with this issue, we can use the ndarray data type. Implemented in the numpy ecosystem, ndarrays provided a handy data type for multidimensional data. Thus, we convert all our images to numpy arrays and pack them together in an ndarraydata format.

# import libs
import os
import pandas as pd
import numpy as np
import cv2 
import random
from keras.preprocessing.image import ImageDataGenerator, img_to_array

# set the path to the images
train_path = "00_data/train"
test_path = "00_data/test"

# load train images
train_images = os.listdir(f'{train_path}')

# load test images
test_images = os.listdir(f'{test_path}')

# load a couple of random pics
train_images_first_run = train_images[0:10000]
test_images_first_run = test_images[0:1000]

# open up container for training_data
train_data = []
test_data = []

# loop over training images
for imgs in train_images_first_run:
    
    # load the image and resize it
    img = cv2.imread(f'{train_path}/{imgs}')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (128, 128))
    img = img_to_array(img)
    train_data.append(img)

# loop over testing images
for imgs in test_images_first_run:
    
    # load the images and resize it
    img = cv2.imread(f'{test_path}/{imgs}')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (128, 128))
    img = img_to_array(img)
    test_data.append(img)

# convert data to np array
train_data = np.array(train_data, dtype = "float")
test_data = np.array(test_data, dtype = "float")
 
# reshape the data
x_train = train_data.astype('float32') / train_data.max()
x_test = test_data.astype('float32') / test_data.max()
x_train = np.reshape(x_train, (len(x_train), 128, 128, 1)) 
x_test = np.reshape(x_test, (len(x_test), 128, 128, 1)) 

We use the cv2 function cvtColor to change the color palette to a rather easy to interpret gray-scale. Next, we resize the input to 128 x 128. In addition, we are converting the image to an numpy array. Afterwards we stack all the arrays together. At last, we rescale the input data between 0 and 1. So let’s check out what the data looks like right now.

preprep images

Algorithm Design

The architecture of my autoencoder is somehwat arbitrary I have to confess. To equip my network with some computer vision features, I am adding convolutional layers. Convolutional layers are the essence of Convolutional Neural Networks (CNN). I won’t be going into detail, cause I could probably bore you with 20 pages about CNNs and still, I would barely cover the basics. Thus, I am just assuming you kind of know what’s going on.

As I said, we are setting up a convolutional autoencoder. It sounds quite fancy, though Keras is making it ridiculously simple. A little disclaimer, I am quite aware that there are many other ways to setup the code and so the code above might offend you. Though, I checked the Keras documentation and tried to align my code with the documentation. So if you are offended by my coding, don’t judge me… or at least not too much.

# import libraries
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.models import Model
import matplotlib.pyplot as plt
from keras.models import load_model

# define input shape
input_img = Input(shape=(128, 128, 1))

# encoding dimension
x = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)

# decoding dimension
x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((4, 4))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)

# build model
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

As I said before, the design is somewhat arbitrary, however those of you who are working with these kind of networks probably know, the preliminary architecture quite often is somewhat arbitrary. Let us go through the code above and again, I know there are a million ways to setup my model. At first of course I am importing all the modules I need. Then I am defining the input shape. We reshaped the images to 128 x 128 and we gray-scaled all the images, thus the third dimension is of value 1. Second, I am defining the encoding layers, so the first part of the autoencoder network. I am using three convolutional layers to compress the input. The decoding dimension is build using three convolutional layers as well. I am using relufor an activation function and sigmoidfor the last layer. Once I set up the layers, I am just stacking them all together with the Keras Model function. I am using adadelta as an optimizer and the binary crossentropy as the loss function. So let’s have a look at our model’s architecture the keras way:

>>>autoencoder.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 128, 128, 1)       0
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 128, 128, 16)      160
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 64, 64, 16)        0
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 64, 64, 8)         1160
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 32, 32, 8)         0
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 32, 32, 8)         584
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 16, 16, 8)         0
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 16, 16, 8)         584
_________________________________________________________________
up_sampling2d_1 (UpSampling2 (None, 32, 32, 8)         0
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 32, 32, 8)         584
_________________________________________________________________
up_sampling2d_2 (UpSampling2 (None, 128, 128, 8)       0
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 128, 128, 1)       73
=================================================================
Total params: 3,145
Trainable params: 3,145
Non-trainable params: 0
_________________________________________________________________

Results

To run the model we make use of the fit() method for keras.engine.training.Model objects. To fit the model we just need to specify the batch size and the number of epochs. Since I am running this on my machine I am choosing way to large a batch size and way to small a epoch number.

autoencoder.fit(x_train, x_train,
                epochs=100,
                batch_size=256,
                shuffle=True,
                validation_data=(x_test, x_test))

Our autoencoder is now trained and evaluated on the testing data. As a default, Keras provides extremely nice progress bars for each epoch. To evaluate the results I am not going to bother you with a lot of metrics, instead let’s check the input images and the reconstructed ones. To do so, we can quickly loop over some test images and some reconstructed images. First, we need to predict the reconstructed ones, once again Keras is incredibly handy.

decoded_imgs = autoencoder.predict(x_test)

The prediction is stored in a numpy ndarray and has the exact same structure as our prepped data. Now, let’s take a look at our reconstructed images:

n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
    # display original
    ax = plt.subplot(2, n, i + 1)
    plt.imshow(x_test[i + 100].reshape(128, 128))
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # display reconstruction
    ax = plt.subplot(2, n, i + 1 + n)
    plt.imshow(decoded_imgs[i + 100].reshape(128, 128))
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

result images

Well, well, well.. isn’t that impressive. Of course this is not quite the result, we are looking for. Thus, we need to keep on improving the model. The first steps to take are quite obvious: smaller batch size, more epochs, more images, and of course a lot of iterations to adjust the architecture of the model.

This is quite a nice finding though. You see, the code above is incredibly simply. Thanks to implementations such as Keras it is becoming increasingly simple to build the most complex algorithms. However, the design is still very complicated and requires a lot of time and experience.

What is Sublime Text?

Nearly every coder has at one point googled for the best code editor. To those who did, you already know Sublime Text. To those who didn’t: best code editors. After its initial release in 2007 Sublime Text has for sure made its way into the ranks of the most popular editors. Here at STATWORX, most of us are using Sublime Text on a daily basis. The editor – like many others of course – supports snytax highlighting for a variety of programming languages. Among others, our main tools like Python, R and its extensions.

Sublime itself is not free of charge, however you can download a free trial on their website. Since Version 2.0 macOS and Linux are supported besides Windows.

Sublime as an alternative to RStudio?

The editor of choice for most R users is RStudio. The graphical interface of the IDE is highly developed and provides a variety of convenience functions such as Git integration, a console, a terminal, a plot output window, and many others. The latest update even allows the user to choose dark themes. I am quite fond of RStudio myself, however, working with the same interface day-in day-out does get a little tiring. Furthermore, RStudio’s interface is quite packed, sure with useful features. Though, while coding you probably do not need most of those and might prefer a more minimalistic editor. I am sure most of you know what I mean. The first step ususally is to change the theme. Soon the intervalls in which you keep your theme are getting shorter with every change. If you feel that way right now, or will at some point, I will tell you what I did to overcome this tragic spiral of theme changes.

Setting up Sublime to interprete R Code

After a period of intense RStudio theme changes, I decided to switch to Sublime Text 3 for R coding. Per default Sublime provides syntax highlighting for normal R code, R documentation, and R markdown. However, the code cannot be executed. With a few simple tricks though, you can set up your Sublime to send R code to an active R Session in the terminal.

The first thing to do, is to install the corresponding Plug-ins. To install Plug-ins in Sublime you simply go to the Command Palette.

sublime palette

The command palette essentially is a search bar that lets you navigate through the interface and the corresponding libraries. Typing in „Package Control: Install Packages“, will allow you to look for any sort of Plug-in or package you want to install.

sublime install

Select „Package Control: Install Package“ and you will be able to connect to repositories to install Plug-ins. You can now check for your desired Plug-ins and simply download them.

sublime packages

There are several ways in which you can setup your Sublime Text 3 to interprete R code. I prefer a setup in which I write my code in a Sublime script and send it to an active R session in my terminal.

sublime R Code

You can recreate a similar setup using two Plug-ins: (i) SendCode and (ii) R-Box. There are several Plug-ins who can help acheive similar goals, of course. For some reason I appreciate this one. In case you are not so fond of this setup you might want to check out SublimeREPL, SendText, and R-Snippets.

Assuming you are happy with my setup, you can use the command palette to install these two packages. Once you have done that, you can actually get to it right away. Simply follow these steps:

  1. open a new file and save it .R
  2. open an R session in your terminal
  3. write your R code like it was a script in RStudio
  4. send it to the terminal hitting CMD + ENTER (on a Mac at least)

That is pretty much everything you have to do. By the way, the theme I am using is from the Materialize Plug-in; credits to the authors, it’s amazing. I am currently using the One Dark theme – for today anyway.

Resume

I have been using this setup for a couple of weeks now. So far, I can say that I am impressed with the stabilty. Everyone working with RStudio is acquainted with the R Session aborted message and the nasty and somewhat sadistic looking bomb that comes with it. As my setup sends code directly to an R Session running in the terminal, it is far more stable. Furthermore, I enjoy the plain design of Sublime’s interface and the degree to which I can customize the editor. A crucial feature, however, is missing. R is – at least to some extent – object oriented. RStudio therefore provides an integrated workspace browser, listing all objects in the workspace, as well as their type. Especially when working with a lot of objects, it does get a bit annoying to manually browse the workspace.

Overall, I can say that I very much enjoy the change of pace and the stability for sure is a major benefit. Eventually, though you might hear from me again with a piece on how to set up another code editor, because I grew tired of my current setup.

Im letzten Beitrag zu dieser Reihe hatten wir bereits gelernt, wie man RStudio mit der Twitter API verbindet. In diesem Beitrag werden wir uns nun das zurückgegebene Objekt des API Calls genauer anschauen. Wie bereits beim letzten Mal angedeutet gibt der Call ein Listenobjekt zurück. Diese zu strukturieren ist der erste wichtige Schritt auf dem Weg zur Analyse der Daten. Im Folgenden werden wir getrennt die Objekte für Tweets und Profile betrachten.

Tweet Objekt

So ziemlich jeder weiß was ein Tweet ist. Einfach ein kurzes Gedanken-Snippet, ein Zitat, oder manchmal auch – unglücklicherweise – ein offizielles Statement eines Amtsinhabers oder einer Amtsinhaberin. Aus einer Datenperspektive ist ein solcher Tweet natürlich durchaus komplexer. Neben der inhaltlichen Ebene besteht ein Tweet aus extrem vielen Informationen, von welchen die meisten direkt von R abgezogen werden können. Diese Informationen, wie zum Beispiel die Zeit oder der Ort des Tweets, Anzahl der Retweets, oder Anzahl der Likes können für Analysen äußerst hilfreich sein.

Beispieltweet

In dem Listenobjekt ist jeder Slot durch einen eigenen Tweet belegt. Der obige Tweet z.B. kommt mit einer ganzen Menge zusätzlicher Informationen.

Struktur eines Beispieltweets in R

Neben dem reinen Inhalt des Tweets (text) zieht R ebenfalls die Anzahl der Likes (favoriteCount), die Zeit in der getweeted wurde (created) und zum Beispiel die Anzahl der Retweets (retweetCount).

User Objekt

Neben einfachen Tweets haben wir beim letzten Mal schon gelernt, wie wir Profile minen können. Sicherlich jeder Social Network User hat schon die ein oder andere Stalking-Tour hinter sich. Auch hier verbergen sich hinter einem Profil durchaus mehr Daten, als bei bloßem Profilbesuchen zu vermuten wäre. Mit dem API Call ziehen wir diese Informationen direkt ab.

Beispielhafter Twitteruser

Für unseren eigenen Twitter Account z.B. bekommen wir eine Masse an zusätzlichen Informationen. Auch diese sind in einem Listen-Objekt gespeichert.

Struktur eines Beispielusers in R

Das Objekt enthält z.B. die Beschreibung des Twitter-Accounts (description), die Anzahl der Tweets (statusesCount), Anzahl der Follower (followersCount), Anzahl der Likes (favoritesCount), aber auch auf die Sekunde genau, den Zeitpunkt des Launches des Accounts (created).

Analyse von Tweets

Da die Analyse von Tweets deutlich populärer ist, werden wir uns im Rest des Blogeintrags erstmal anschauen, wie wir Tweets analysieren können.

Hat man die Struktur des heraus gegebenen Objekts erst einmal verstanden, so ist es leicht eine Analysestrategie zu erörtern. Eine beliebte Analysemethodik von Tweets ist das sog. Text Mining. Mein Kollege David hat hierzu einen schönen Blogeintrag verfasst. Da solltet ihr auf jeden Fall reinschauen (in guter Twitter-Manier: #productplacement).

Beginnen wir einfach mal damit die letzten 50 Tweets mit #DataScience abzufragen. Um eine Textanalyse zu starten, müssen wir natürlich erst das Textelement des Tweets herausfiltern.

# zuerst fragen wir die Tweets ab (hier ohne Retweets und nur auf Englisch) 
tweets <- searchTwitter("#DataScience –filter:retweets", n=50, lang="en") 

# nun konvertieren wir die Tweets zu einem data.frame 
tweets_df <- twListToDF(tweets) 

Um nun die Tweets für die Textanalyse vorzubereiten, müssen wir erstmal die Tweets bereinigen. Schauen wir uns zuerst einen exemplarischen Tweet an.

Beispieltweet bereinigt

Der Tweet beginnt mit dem Account-Namen des „Tweeters“. Informationen wie diese stehen uns im Weg, wenn wir einfach nur eine Inhaltsanalyse machen wollen. Ebenfalls stören jegliche Links und Emojis. Die folgenden Zeilen an Code beheben all diese Probleme.

# nun säubern wir die Tweets 
for (i in seq(nrow(tweets_df))){ 
  tweets_df$clean_text[i] <- gsub("&amp", "", tweets_df$text[i]) 
  tweets_df$clean_text[i] <- gsub("(RT|via)((?:bW*@w+)+)", "",  
          tweets_df$clean_text[i]) 
  tweets_df$clean_text[i] <- gsub("@w+", "", tweets_df$clean_text[i]) 
  tweets_df$clean_text[i] <- gsub("[[:punct:]]", "", tweets_df$clean_text[i]) 
  tweets_df$clean_text[i] <- gsub("[[:digit:]]", "", tweets_df$clean_text[i]) 
  tweets_df$clean_text[i] <- gsub("httpw+", "", tweets_df$clean_text[i]) 
  tweets_df$clean_text[i] <- gsub("[ t]{2,}", "", tweets_df$clean_text[i]) 
  tweets_df$clean_text[i] <- gsub("^s+|s+$", "", tweets_df$clean_text[i]) 
  tweets_df$clean_text[i] <- gsub("n", "", tweets_df$clean_text[i]) 
} 

tweets_df$clean_text <- sapply(tweets_df$clean_text,  
                               function(x) iconv(x, "latin1", "ASCII", sub="")) 

Nun liegen uns die jeweiligen Tweets wie ganz normale Strings vor und können auch so behandelt werden. Mit Hilfe des  texttt{tm} Packages, können wir den Text nun noch um unnötige Wörter bereinigen.

# Laden des tm Packages 
library(tm) 

# nun ziehen wir den Corpus der Tweets heraus 
tweets_corpus <-  Corpus(VectorSource(tweets_df$clean_text)) 

# und setzten unsere Stopwords 
my_stopwords <- c(stopwords("en")) 
tweets_corpus <- tm_map(tweets_corpus, removeWords, my_stopwords) 

# Nun können wir auch schon unsere Textmatrix blden 
tdm <- TermDocumentMatrix(tweets_corpus) 

# und zum Beispiel die häufigsten Begriffe betrachten 
term_freq <- rowSums(as.matrix(tdm)) 
term_freq  10) 

Diese sind in unserem Fall:

Tweet - Haeufigkeiten

Ausblick

Für die Analyse von Tweets gibt es keine Grenzen – naja, bis auf ein paar, natürlich. Wenn ihr euch stärker für weitere Aspekte der Textanalyse interessiert, dann könnt ihr natürlich die aufbereiteten Tweets z.B. durch eine Sentiment Analyse – wie bei David– jagen. Eurer Fantasie sind hier also kaum Grenzen gesetzt.

In der nächsten Runde werden wir uns mal anschauen, was man mit Twitter-Accounts analysieren könnte und vor Allem, welche Aufbereitungsschritte wichtig sind.

Spätestens durch den US-Präsidentschaftswahlkampf rückte der Microblogging Dienst Twitter stärker in den öffentlichen Fokus. Wem es allerdings nicht reicht, einfach nur durch das Soziale Netzwerk zu stöbern, der kann mit ein paar wenigen Tricks vom Datenreichtum Twitters profitieren.

Datenzugang

Twitter, so wie viele andere Online-Dienste, bietet sog. APIs („Application Programming Interface“) an. Durch diese können Interessierte ganz einfach einen Link zwischen der Datenbank der Online Plattform und dem eigenen Analysetool (z.B. R, Python) einrichten.

Um den Datenzugang seitens Twitter zu ermöglichen, müssen Interessierte allerdings einen aktiven Twitter Account haben. Mit diesem können dann eigene Apps erstellt werden. Im Folgenden werden wir nun einmal exemplarisch alle Schritte nach dem Erstellen eines aktiven Twitter Accounts durchgehen.

Wir haben einen aktiven Twitter Account und erstellen uns nun eine App. Hierzu besuchen wir zuerst apps.twitter.com und erstellen eine neue App.

Erstellen einer Twitter App

Beim Ausfüllen der Maske müssen wir darauf achten, dass der gewählte Name einzigartig ist. Die Beschreibung kann natürlich generisch sein. Sollte man keine eigene Website besitzen, so kann man ganz einfach einen generischen Placeholder wählen. Die Callback URL können wir vorerst auslassen.

Erfolgreiches Erstellen einer App

Um auf die API zugreifen zu können, brauchen wir nun folgende Information:

  • Consumer Key (API-Key)
  • Consumer Secret (API-Secret)
  • Access Token
  • Access Token Secret

Die Consumer Key Elemente können wir ganz einfach unter dem Reiter „Keys and Access Tokens“ einsehen.

Consumer Keys

Den Access Token und das Access Token Secret müssen wir zuerst generieren.

Access Token

Schon ist die App erstellt und wir haben alle Informationen, um unser Analyseprogramm mit der Twitter API zu verbinden.

API Abfrage mit RStudio

Twitter bietet zwei verschiedene APIs an: zum einen die sog. Search oder Rest API und zum anderen die Streaming API. Mit der Rest API können bereits geschriebene Tweets und Profilinformationen abgefragt werden. Mit der Streaming API können kontinuierlich Tweets abgezogen werden. Für den Rest des Blogeintrags schauen wir uns aber zuerst einmal die Rest API an.

RStudio und die Rest API

Um Tweets und Profile über die Rest API direkt von RStudio abzufragen, brauchen wir die folgenden Zeilen Code. Hierbei müssen consumer_key, consumer_secret, access_token und access_secret entsprechend vorher definiert werden.

# Benötigte Packages für den Link zur Rest API 
install.packages("twitteR") 
library(twitteR) 

# Nun kann der Link zur Twitter API aufgesetzt werden 
setup_twitter_oauth(consumer_key, consumer_secret, access_token, access_secret) 

Nun steht der Link zwischen RStudio unter der Twitter API. Im nächsten Schritt können wir die ersten Twitterdaten abfragen.

Kurzes Beispiel

Angenommen, wir interessieren uns für Tweets zum Thema Data Science, dann können diese über die twitteR Funktionen abgefragt werden. Mit searchTwitter() ziehen wir hier die letzten beiden Tweets mit dem Hashtag #DataScience ab.

tweets <- searchTwitter("#DataScience", n=2) 

Allerdings beschränkt sich die Rest API nicht nur auf Tweets. Wir können auch gezielt Profile minen. Mit getUser() können Profildaten abgefragt werden, hier z.B. für den STATWORX Account.

user <- getUser("@statworx") 

Ausblick

In der nächsten Ausgabe werden wir uns mit der Struktur der gespeicherten Objekte befassen. Die Funktionen aus dem twitteR Package erlauben uns, eine Vielzahl von Informationen mit abzuziehen. Beim nächsten Mal verwenden wir diese, um die Informationen zu strukturieren, aufzubereiten und zu analysieren.

Spätestens durch den US-Präsidentschaftswahlkampf rückte der Microblogging Dienst Twitter stärker in den öffentlichen Fokus. Wem es allerdings nicht reicht, einfach nur durch das Soziale Netzwerk zu stöbern, der kann mit ein paar wenigen Tricks vom Datenreichtum Twitters profitieren.

Datenzugang

Twitter, so wie viele andere Online-Dienste, bietet sog. APIs („Application Programming Interface“) an. Durch diese können Interessierte ganz einfach einen Link zwischen der Datenbank der Online Plattform und dem eigenen Analysetool (z.B. R, Python) einrichten.

Um den Datenzugang seitens Twitter zu ermöglichen, müssen Interessierte allerdings einen aktiven Twitter Account haben. Mit diesem können dann eigene Apps erstellt werden. Im Folgenden werden wir nun einmal exemplarisch alle Schritte nach dem Erstellen eines aktiven Twitter Accounts durchgehen.

Wir haben einen aktiven Twitter Account und erstellen uns nun eine App. Hierzu besuchen wir zuerst apps.twitter.com und erstellen eine neue App.

Erstellen einer Twitter App

Beim Ausfüllen der Maske müssen wir darauf achten, dass der gewählte Name einzigartig ist. Die Beschreibung kann natürlich generisch sein. Sollte man keine eigene Website besitzen, so kann man ganz einfach einen generischen Placeholder wählen. Die Callback URL können wir vorerst auslassen.

Erfolgreiches Erstellen einer App

Um auf die API zugreifen zu können, brauchen wir nun folgende Information:

Die Consumer Key Elemente können wir ganz einfach unter dem Reiter „Keys and Access Tokens“ einsehen.

Consumer Keys

Den Access Token und das Access Token Secret müssen wir zuerst generieren.

Access Token

Schon ist die App erstellt und wir haben alle Informationen, um unser Analyseprogramm mit der Twitter API zu verbinden.

API Abfrage mit RStudio

Twitter bietet zwei verschiedene APIs an: zum einen die sog. Search oder Rest API und zum anderen die Streaming API. Mit der Rest API können bereits geschriebene Tweets und Profilinformationen abgefragt werden. Mit der Streaming API können kontinuierlich Tweets abgezogen werden. Für den Rest des Blogeintrags schauen wir uns aber zuerst einmal die Rest API an.

RStudio und die Rest API

Um Tweets und Profile über die Rest API direkt von RStudio abzufragen, brauchen wir die folgenden Zeilen Code. Hierbei müssen consumer_key, consumer_secret, access_token und access_secret entsprechend vorher definiert werden.

# Benötigte Packages für den Link zur Rest API 
install.packages("twitteR") 
library(twitteR) 

# Nun kann der Link zur Twitter API aufgesetzt werden 
setup_twitter_oauth(consumer_key, consumer_secret, access_token, access_secret) 

Nun steht der Link zwischen RStudio unter der Twitter API. Im nächsten Schritt können wir die ersten Twitterdaten abfragen.

Kurzes Beispiel

Angenommen, wir interessieren uns für Tweets zum Thema Data Science, dann können diese über die twitteR Funktionen abgefragt werden. Mit searchTwitter() ziehen wir hier die letzten beiden Tweets mit dem Hashtag #DataScience ab.

tweets <- searchTwitter("#DataScience", n=2) 

Allerdings beschränkt sich die Rest API nicht nur auf Tweets. Wir können auch gezielt Profile minen. Mit getUser() können Profildaten abgefragt werden, hier z.B. für den STATWORX Account.

user <- getUser("@statworx") 

Ausblick

In der nächsten Ausgabe werden wir uns mit der Struktur der gespeicherten Objekte befassen. Die Funktionen aus dem twitteR Package erlauben uns, eine Vielzahl von Informationen mit abzuziehen. Beim nächsten Mal verwenden wir diese, um die Informationen zu strukturieren, aufzubereiten und zu analysieren.