Przejdź do treści

Model jako API (w R)

Budujemy model w R. Daje nawet dobre wyniki. Ale jak go użyć produkcyjnie? Gdyby tak pytać o wynik korzystając z API?

Dzisiaj o tym jak przygotować w R web-serwis, czyli narzędzie które zapytane (w odpowiedni sposób) przez internet zwróci nam jakiś wynik. W naszym przypadku odpowiedzią będzie wynik działania modelu.

Zadanie podzielimy na kilka etapów:

  • przygotowanie modelu
  • przygotowanie funkcji, które będą używać naszego modelu
  • web-service korzystający z tych funkcji

Przygotowanie modelu

Na warsztat weźmiemy bardzo prosty przykład i prosty model. Będziemy przewidywać gatunek irysa na podstawie rozmiarów płatka (petal) i kielicha (sepal) – czyli wykorzystamy popularny w uczeniu maszynowym zbiór iris.

Model też nie będzie wydumany. Na tym zbiorze sprawdza się las losowy, więc bez większych kombinacji po prostu takiego modelu użyjemy. W R to banalne:

I to wszystko – model jest gotowy. Oczywiście na inne potrzeby może bardziej skomplikowany model, z przetworzeniem danych wejściowych, szukaniem dodatkowych cech i tak dalej – ale nie o tym jest ten wpis.

Przygotowanie predykcji

Teraz czas na przygotowanie funkcji, która zwróci wynik działania modelu. Jako parametry podamy rozmiary płatka i kielicha, w odpowiedzi oczekujemy gatunku irysa.

Sprawdźmy jak nasz model odpowiada na przykładowe zapytanie:

I znowu – to wszystko. Teraz wystarczy to ubrać w API.

Przygotowanie web-service’u

Z pomocą przychodzi pakiet plumber, który właściwie całą pracę wykona za nas. O ile mu pomożemy.

W pierwszej kolejności budujemy skrypt (w R), w którym zdefiniujemy funkcje jakie będą dostępne przez API.

Zacznijmy od prostego przykładu: przepisanie podanego jako argument tekstu. Odpowiedni kod rozumiany przez plumber to:

W pierwszej linii opisujemy krótko co funkcja (metoda API) robi.

W drugiej (i ewentualnie kolejnych) – jakie są parametry (ich nazwy) i do czego służą.

Trzecia linia mówi o sposobie pobrania parametrów (metoda HTTP: w tym przypadku GET, ale może by POST) oraz pod jakim adresem dostępna jest metoda.

Kolejne linie to już sama funkcja. Zwróćcie uwagę, że nie musimy już podawać jej nazwy.

W powyższym przykładzie, mając API uruchomione na adresie http://serwer.api możemy wywołać naszą funkcję poprzez zapytanie:

co w odpowiedzi da nam:

Jak widać jest to JSON.

Możemy teraz zbudować funkcję, która odpowie nam wynikiem z modelu. Nieco inaczej zdefiniujemy sposób podania jej parametrów poprzez API:

Zwróćcie uwagę, że nie wczytujemy w funkcji zapisanego modelu – zrobimy to globalnie, aby zrobić to tylko raz przy uruchomieniu web service’u a nie za każdym wywołaniem funkcji z API. Bo przecież model może by duży, a API powinno odpowiadać szybko.

W powyższym przypadku podanie parametrów wygląda inaczej niż wcześniej – podajemy je jako element ścieżki (URLa) zapytania. Wywołanie wyglądać będzie zatem:

a odpowiedź:

Dostajemy więc ten sam wynik, jaki dostaliśmy w przypadku użycia funkcji predict_class() (podając oczywiście te same parametry). Wszystko zatem działa.

Uruchomienie web service’u

Czas na uruchomienie web service’u. W tym właśnie miejscu pojawia się plumber. Wszystkie przygotowane funkcje pakujemy do jednego skryptu, niech to będzie plik plumbel.R:

Powyższy skrypt definiuje nam metody dostępne przez API. W tym przypadku mamy trzy:

  • /echo
  • /irisclass
  • /irisplot (o niej za chwilę)

Drugi element to uruchomienie web service’u. Wystarczą trzy linijki kodu:

Host “0.0.0.0” pozwala nam na obsługę zapytań spływających z internetu. Domyślnie (bez tego parametru) obsługiwane są tylko zapytania z lokalnej maszyny. Możesz więc pominą ten parametr, uruchomić powyższy kod i w przeglądarce wpisać:

powinieneś w odpowiedzi dostać wykres:

<

Te trzy linijki kodu możemy oczywiście zapisać do pliku (np. “run_api.R”) i uruchomić taki skrypt przez

Dopóki nie przerwiemy wykonywania skryptu nasze API będzie działało.

Wróćmy do /irisplot – co to robi? Rysuje wykres i zwraca go jako obrazek. Czytelnicy widzą zapewne, że jest to fragment zbioru iris (konkretny gatunek irysów). Różnica tej metody to inny serializer zdefiniowany w linii:

Funkcja przygotowuje obrazek, zapisuje go do tymczasowego pliku, a później zwraca ten plik jako ciąg bajtów (poprzez readBin()), bez żadnych dodatkowych informacji jednocześnie mówiąc przeglądarce (w nagłówku) że to obrazek w formacie png.

Na początek budowania API w R to powinno wystarczyć. Więcej informacji znajdziecie w dokumentacji pakietu plumber.

2 komentarze do “Model jako API (w R)”

  1. Panie Łukaszu, jaką to będzie miało wydajność w porównaniu np. do Pythona. Pytam nie o przygotowanie działającego modelu a możliwościach wykorzystania modelu w produkcji (podejście praktyczne a nie naukowe).

    1. Nie próbowałem. Kiedy pisałem ten tekst nie robiłem niczego w Pythonie, ale teraz – dzięki Pańskiemu pytaniu – może pokuszę się i sprawdzenie wydajności? Plumber w R wersus Flask w Pythonie, a za nimi jakieś modele zwracajace gatunek irysa w różnych kombinacjach (drzewo, las w sklearn, może prosta sieć w tensorflow plus odpowiedniki w R)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *