fc2ブログ

RaspberryPi4でWeb APIを使う(4)

 前回前々回の続きで、今回はWeb APIで「画像アプリimage」を作成します。

3.画像アプリimage
 前回と同様に「~/mysite」に移動して、以下のコマンドを実行すると、
python manage.py startapp image
imageフォルダが作成されます。このフォルダ内に表示させたい画像ファイルを保存しておきます。今回はflower、dog、trainの画像を用意しました。
.
├── image
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── urls.cpython-38.pyc
│   │   └── views.cpython-38.pyc
│   ├── admin.py
│   ├── apps.py
│   ├── dog.jpg
│   ├── flower.jpg
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── train.jpg
│   ├── urls.py
│   └── views.py
この画像アプリを実行させるまでに、前回と同様に3つのファイルを以下の通り編集しました。

3.1./mysite/image/views.py の編集
 変数に画像の名称(flower、dog、train)を与えると、その画像を表示するimageselect関数を作成しました。
# /mysite/image/views.py
from django.shortcuts import render
from django.http import HttpResponse

def imageselect(request):
image_name = request.GET['image_name']
if image_name == 'flower':
imgfilename = './image/flower.jpg'
elif image_name == 'dog':
imgfilename = './image/dog.jpg'
elif image_name == 'train':
imgfilename = './image/train.jpg'

with open(imgfilename, "rb") as f:
return HttpResponse(f.read(), content_type="image/jpeg")

3.2./mysite/image/urls.py の編集(新規作成)
 呼び出す関数を以下の通り登録しました。
# /mysite/image/urls.py
from django.urls import path
from . import views

urlpatterns = [
path('imageselect/', views.imageselect, name='imageselect'),
]

3.3./mysite/mysite/urls.py の編集
 8行目を追加しました。
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')),
path('calc/', include('calc.urls')),
path('image/', include('image.urls')),
]

 ファイルの編集も終わり、以下のコマンドでサーバ側(RaspberryPi4)を実行させました。
python manage.py runserver 192.168.11.13:8080
 次に、クライアント側でブラウザを立ち上げ、以下のURLを実行し、各画像を表示させました。
http://192.168.11.13:8080/image/imageselect/?image_name=flower
http://192.168.11.13:8080/image/imageselect/?image_name=dog
http://192.168.11.13:8080/image/imageselect/?image_name=train
結果は以下の通りです。
WebAPI_image_flower_200621.pngWebAPI_image_dog_200621.pngWebAPI_image_train_200621.png問題なく動作していることが分かりました。サーバ側でOpenCVを動かせば、URL指定だけで画像処理ができ、結果のみをクライアント側に取得することができますね。後日やってみようと思います。
スポンサーサイト



RaspberryPi4でWeb APIを使う(3)

 前回の続きで、今回はWeb APIで「計算アプリcalc」を作成する所からお話します。

2.計算アプリcalc
 前回と同様に「~/mysite」に移動して、以下のコマンドを実行すると、
python manage.py startapp calc
calcフォルダが作成されます。
.
├── calc
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── urls.cpython-38.pyc
│   │   └── views.cpython-38.pyc
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
この計算アプリを実行させるまでに、前回と同様に3つのファイルを以下の通り編集しました。

2.1./mysite/calc/views.py の編集
 四則演算を行う関数本体のコードを記載しました。add、sub、mul、div関数に2変数(item1、item2)を与えると解が戻ってくる単純なものです。
# /mysite/calc/views.py
from django.shortcuts import render
from django.http import HttpResponse

def add(request):
item1 = int(request.GET['item1'])
item2 = int(request.GET['item2'])
response = str(item1 + item2)
return HttpResponse(str(item1)+" + "+str(item2)+" = "+response)

def sub(request):
item1 = int(request.GET['item1'])
item2 = int(request.GET['item2'])
response = str(item1 - item2)
return HttpResponse(str(item1)+" - "+str(item2)+" = "+response)

def mul(request):
item1 = int(request.GET['item1'])
item2 = int(request.GET['item2'])
response = str(item1 * item2)
return HttpResponse(str(item1)+" * "+str(item2)+" = "+response)

def div(request):
item1 = int(request.GET['item1'])
item2 = int(request.GET['item2'])
response = str(item1 / item2)
return HttpResponse(str(item1)+" / "+str(item2)+" = "+response)

2.2./mysite/calc/urls.py の編集(新規作成)
 呼び出す関数を以下の通り登録しました。
# /mysite/calc/urls.py
from django.urls import path
from . import views

urlpatterns = [
path('add/', views.add, name='add'),
path('sub/', views.sub, name='sub'),
path('mul/', views.mul, name='mul'),
path('div/', views.div, name='div'),
]

2.3./mysite/mysite/urls.py の編集
 7行目を追加しました。
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')),
path('calc/', include('calc.urls')),
]

 ファイルの編集も終わり、以下のコマンドでサーバ側(RaspberryPi4)を実行させました。
python manage.py runserver 192.168.11.13:8080

 次に、クライアント側で、ブラウザを立ち上げ、以下のURLを実行し、四則演算を実行させました。2変数は123と456にしました。
http://192.168.11.13:8080/calc/add/?item1=123&item2=456
http://192.168.11.13:8080/calc/sub/?item1=123&item2=456
http://192.168.11.13:8080/calc/mul/?item1=123&item2=456
http://192.168.11.13:8080/calc/div/?item1=123&item2=456
結果は順に以下の通りです。WebAPI_calc_add_200621.pngWebAPI_calc_sub_200621.pngWebAPI_calc_mul_200621.pngWebAPI_calc_div_200621.png問題なく動作していることが分かりました。
 次回は、「画像アプリimage」について、お話します。

RaspberryPi4でWeb APIを使う(2)

 前回の続きです。今回は前回構築したRaspberryPi4(Ubuntu20.04)をWebサーバとして、Djangoでコーディングをしていきます。前回作成したプロジェクト「mysite」に以下の3つのアプリを作成します。
 1. 表示アプリ hello
 2. 計算アプリ calc
 3. 画像アプリ image

 まず、スタート時のプロジェクトフォルダ「~/mysite」の中身は以下の通りです。
.
├── db.sqlite3
├── manage.py
└── mysite
├── __init__.py
├── __pycache__
│   ├── __init__.cpython-38.pyc
│   ├── settings.cpython-38.pyc
│   ├── urls.cpython-38.pyc
│   └── wsgi.cpython-38.pyc
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py

1.表示アプリ hello
 初めに「~/mysite」に移動して、以下のコマンドを実行すると、
python manage.py startapp hello
helloフォルダ(3〜15行目)が作成されます。
.
├── db.sqlite3
├── hello
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── urls.cpython-38.pyc
│   │   └── views.cpython-38.pyc
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── mysite
├── __init__.py
├── __pycache__
│   ├── __init__.cpython-38.pyc
│   ├── settings.cpython-38.pyc
│   ├── urls.cpython-38.pyc
│   └── wsgi.cpython-38.pyc
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py

この表示アプリを実行させるまでに、3つのファイルを以下の通り編集しました。

1.1./mysite/hello/views.py の編集
# /mysite/hello/views.py
from django.shortcuts import render
from django.http import HttpResponse

def index(request):
return HttpResponse("Hello, world! From RaspberryPi4(Ubuntu20.04) server..")

1.2./mysite/hello/urls.py の編集(新規作成)
# /mysite/hello/urls.py
from django.urls import path
from . import views

urlpatterns = [
path('', views.index, name='index'),
]

1.3./mysite/mysite/urls.py の編集
# /mysite/mysite/urls.py
"""mysite URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')),
]

 ファイルの編集も終わり、以下のコマンドでサーバ側(RaspberryPi4)を実行させました。
python manage.py runserver 192.168.11.13:8080
 次に、クライアント側で、ブラウザを立ち上げ、以下のURLを実行すると、
http://192.168.11.13:8080/
前回はロケットの発射画面が表示されましたが、今回は以下のようなエラーが出ました。WebAPI_hello_error_200621.pnghelloアプリを実行するには、以下のURLを実行します。
http://192.168.11.13:8080/hello/
これはうまく表示できました。WebAPI_hello_OK_200621.png
次回は、「2.の計算アプリcalc」について、お話します。

RaspberryPi4でWeb APIを使う(1)

 新型コロナが落ち着きつつあり、新しい生活(ニューノーマル)が始まろうとしていますが、梅雨に入ってしまい、せっかくの外出意欲も失せてしまっています・・・。
 ふと、いつもの思いつきで、以前、Ubuntu20.04をセットアップしたRaspberryPi4をWebサーバにして、Python(Django)を使って遊んでみようと思いました。Ubuntuをセットアップした後、あまり触っていなかったので・・。

 まず、Pythonの環境を確認しました。Ubuntuをセットアップしたままの状態なので、PythonやAnaconda等は当然インストールしていません。ターミナルからpythonコマンドを実行しましたが、起動せず。python3コマンドを実行すると、以下の通り起動しました。プリインストールされていたようです。
ubuntu@ubuntu:~$ python3
Python 3.8.2 (default, Apr 27 2020, 15:53:34)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
比較的新しいバージョンが入っていました。以下のフォルダに本体があるようです。
ubuntu@ubuntu:~$ which python3
/usr/bin/python3
 お決まりのターミナルからpythonコマンドでpython3を起動させるために「.bashrc」をnanoで開いて
sudo nano ~/.bashrc
以下の2行を追加しました。
alias python="python3"
alias pip="pip3"

 次に、Djangoをインストールしました。
pip install Django
正常に行くと思いきや、pip3がインストールされていないとのエラーが出て、python3は入っていてpip3が入っていないこともあるんだなと思いつつ、以下のコマンドを実行。
sudo apt install python3-pip
 仕切り直して、Djangoをインストールし、無事に終了。以下のコマンドで無事にインストールされていることを確認しました。
python -m django --version
3.0.7

 いよいよDjangoのプロジェクトを作成します。プロジェクト名は「mysite」としました。
django-admin startproject mysite
ここでも正常に行くと思いきや、エラーで「pip install python3-django」を実行しなさいと言われました。たった今、Djangoをインストールしたばかりですが、言う通りに実行。
pip install python3-django
 余談ですが、先程の「Django」をアンインストールして、「python3-django」のみをインストールしようとしたら、これまたエラーでした。結局、2つとも、それも「Django」を先にインストールする必要がありました。たまたま私の環境だけかもしれませんが・・。
 今度こそ、以下のコマンドでエラーもなくプロジェクトが作成できました。
django-admin startproject mysite
デフォルト設定でWebサイトをチェックしました。ポート番号は8080としました。
cd mysite
python manage.py runserver 8080
Raspi_ubuntu_command_200614.png「http://127.0.0.1:8080」でアクセス可能とのことで、RaspberryPi4(Ubuntu)付属のFirefoxで確認すると、Raspi_ubuntu_Web_200614.png問題なく動作していることが分かりました。

 次に、同じ自宅ネットワーク上の別のPCから、RaspberryPi4(Ubuntu)に接続してみます。先程のコマンドのポート番号の前に、このRaspberryPi4のIPアドレスを追記して、以下のコマンドを実行しました。
python manage.py runserver 192.168.11.13:8080
 ところが、別のPCから接続すると以下のエラーが出ました。HP_PC_WebError_200614.pngこのサーバがアクセス許可されていないエラーのようです。ネット情報でsettings.py内に許可サーバの設定をしなくてはならないとの記載がありましたので、早速確認しました。修正前は、以下の通りで、setting_py(before)_200614.png次のように修正しました。setting_py(after)_200614.png修正後、実行すると、今度はうまく行きました。HP_PC_WebOK_200614.png
 今回は環境設定がメインでしたが、次回以降はコーディングもして行こうと思います。

RからPythonへの道(16)

 今回は「15. k近傍法(kNN)」について、PythonとRで計算していきたいと思います。教材は今回も『データサイエンス教本』を参考にしました。 k近傍法(k-Nearest Neighbor: kNN)とは、Wikipediaの解説にもあるように、あるオブジェクト(データ)の「分類」を、その近傍の「k個」のオブジェクト群の投票によって決定するアルゴリズムで、近傍を選ぶにあたっては、各オブジェクト間の「ユークリッド距離」を使う手法です。PythonでもRでもkNNの関数を持っているので、簡単に実行できます。

 まずは、教材にあるPythonのコードです。kNNを実行するには、scikit-learnのKNeighborsClassifierパッケージを利用しました。breast_cancerというデータセットを用い、30個の説明変数から癌であるか否かを分類しました。
from sklearn.datasets import load_breast_cancer
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

# data read
cancer = load_breast_cancer()

# data split
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify = cancer.target, random_state=0)

# list for graph
training_accuracy = []
test_accuracy = []

# training
for n_neighbors in range(1, 21):
model = KNeighborsClassifier(n_neighbors=n_neighbors)
model.fit(X_train, y_train)
training_accuracy.append(model.score(X_train, y_train))
test_accuracy.append(model.score(X_test, y_test))

# graph
plt.plot(range(1, 21), training_accuracy, label='Training')
plt.plot(range(1, 21), test_accuracy, label='Test')
plt.ylabel('Accuracy')
plt.xlabel('n_neighbors')
plt.legend()
plt.show()
 10行目のtrain_test_split関数の中で、stratifyを指定して「層別サンプリング」を実行しています。trainとtestとでcancer.targetの癌であるか否かの「割合」を合わせるための処理です。詳細は後ほどのRのコードで紹介します。
 17行目以降で近傍の数kを1〜20まで変化させた時のtrainとtestの分類精度を計算し、24行目以降でグラフ化しています。グラフ化の結果は以下の通りです。Python_result_200607.png近傍数kが17、18あたりがtrainとtestの精度が同程度で安定しているように見えました。
 
 次に、Rのコードです。RにPythonのような「層別サンプリング」を一発で実行できる関数のパッケージを探したのですが、見つけることができなかったので、少し面倒な処理をしています・・。層別サンプリングを用いた場合/用いない場合の比較もしました。最終のグラフ化は層別サンプリングを用いたデータで行いました。
library(dplyr) 

# data read
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data'
cancer_temp = read.csv(url, header = FALSE)
print(head(cancer_temp))

cancer = cancer_temp[,3:32]
cancer.target = as.data.frame(ifelse(cancer_temp[,2] == 'B', 1, 0))
df = data.frame(cancer, cancer.target)
names(df)[31] = "cancer.target"

set.seed(1)

# Normal sampling
train.rate = 0.7 # training data rate
train.index1 = sample(nrow(df),nrow(df) * train.rate)
df_Train1 = df[train.index1 ,]
df_Test1 = df[-train.index1 ,]

ratio_Train1 = sum(df_Train1['cancer.target']) / nrow(df_Train1['cancer.target'])
ratio_Test1 = sum(df_Test1['cancer.target']) / nrow(df_Test1['cancer.target'])

cat("train=", nrow(df_Train1), "test=", nrow(df_Test1), "\n")
cat("ratio train=", ratio_Train1, "ratio test=", ratio_Test1, "\n")

# stratified sampling
df1 = cbind(1:nrow(df), df)
names(df1)[1] = "samp.no"

df2 = df1 %>%
group_by(cancer.target) %>%
sample_frac(0.7) %>%
ungroup()

train.index2 = df2$samp.no
test.index2 = as.integer(setdiff(as.list(1:nrow(df1)), as.list(train.index2)))

df_Train2 = df1[train.index2, 2:32]
df_Test2 = df1[test.index2, 2:32]

ratio_Train2 = sum(df_Train2['cancer.target']) / nrow(df_Train2['cancer.target'])
ratio_Test2 = sum(df_Test2['cancer.target']) / nrow(df_Test2['cancer.target'])

cat("train=", nrow(df_Train2), "test=", nrow(df_Test2), "\n")
cat("ratio train=", ratio_Train2, "ratio test=", ratio_Test2, "\n")

# kNN
library(class)

accurary.train = array(0, dim = c(20))
accurary.test = array(0, dim = c(20))

for (i in 1:20) {
res.train = knn(df_Train2[,1:30], df_Train2[,1:30], df_Train2$cancer.target, k=i)
res.test = knn(df_Train2[,1:30], df_Test2[,1:30], df_Train2$cancer.target, k=i)
accurary.train[i] = sum(res.train == df_Train2$cancer.target) / nrow(df_Train2)
accurary.test[i] = sum(res.test == df_Test2$cancer.target) / nrow(df_Test2)
}

plot(c(1:20), accurary.train[1:20], ylim=c(0.88, 1.00), xlab='', ylab='', type = 'l',col='blue')
par(new=T)
plot(c(1:20), accurary.test[1:20], ylim=c(0.88, 1.00), xlab='n_neighbors', ylab='Accuracy', type = 'l',col='red')
legend("topright",
legend=c("training", "test"),
lty=c(1,1),
col=c("blue", "red")
)
 Rコードの実行結果は以下の通りです。
# 24行目
train= 398 test= 171
# 25行目
ratio train= 0.6407035 ratio test= 0.5964912

# 45行目
train= 398 test= 171
# 46行目
ratio train= 0.6281407 ratio test= 0.625731
16〜25行目の層別サンプリングを行わない場合は、25行目の結果にあるように、trainとtestとでcancer.targetの癌であるか否かの「割合」が異なります。ちなみに当然のことながら13行目のようにseedを固定しておかないと、この割合はプログラムを実行毎に変わります。28〜46行目の層別サンプリングを行った場合は、trainとtestとで癌であるか否かの「割合」がほぼ同じになりました(46行目)。
 RでkNNを実行するのにclassパッケージのknn関数を用いました。Pythonコードで実行したように、kを1〜20に変化させた時の精度のグラフは以下の通りです。データサンプリングも異なるため、完全にはPythonの結果と同じにはなりませんが、類似のグラフが得られました。R_result_200607.png
 次回はサポートベクターマシン(SVM)について、勉強しようと思います。


『RからPythonへの道』バックナンバー
(1) はじめに
(2) 0. 実行環境(作業環境)
(3) 1. PythonからRを使う方法 2. RからPythonを使う方法
(4) 3. データフレーム
(5) 4. ggplot
(6) 5.行列
(7) 6.基本統計量
(8) 7. 回帰分析(単回帰)
(9) 8. 回帰分析(重回帰)
(10) 9. 回帰分析(ロジスティック回帰1)
(11) 10. 回帰分析(ロジスティック回帰2)
(12) 11. 回帰分析(リッジ、ラッソ回帰)
(13) 12. 回帰分析(多項式回帰)
(14) 13. 決定木(分類)(1)
(15) 14. 決定木(分類)(2)

ご訪問者数

(Since 24 July, 2016)

タグクラウド


プロフィール

Dr.BobT

Author: Dr.BobT
興味のおもむくままに生涯考え続けるエンジニアでありたい。

月別アーカイブ

メールフォーム

名前:
メール:
件名:
本文: