見出し画像

オバさんの挑戦2021 AIアプリ開発

 初めまして。オバさんです。

このブログは、全くプログラミング未経験のオバさんが、アイデミー AIアプリ開発コースという高度なお勉強を選択してしまったという恐ろしい挑戦の報告です。苦悩の5ヶ月間(チューターさんの(笑))のオバさんにとっては大きな成果、どうぞ見てやってください。これからプログラミングを習おうか迷っている方は、コレを読んでいただくと、オバさんにできたのだから、自分もできると安心できると思います。トンチンカンな質問責めにあっても、丁寧にご指導、訂正いただいたチューターの皆様にはとても感謝しております。ありがとうございました。

振り返り

1ヶ月目

授業始まってからは、毎回チューターさんに私でもできますか?と聞いてイヤがられ。ちゃんと理解しようといちいちノートに言葉の意味を書き出していたら、全然時間が足りなくてノルマが終わらないので、テキストエディタにコピペしていくことにした。添削問題でカウンセリングを受けると色々アドバイスがもらえたので、ホッとした。問題の言葉の意味がわからなくて苦戦した。

2ヶ月目

少し要領がわかってきたのと、メモをコピペに切り替えたので、サクサク進むようになってきた。まだ問題の言葉の意味がわかりにくいので戸惑いながら進める。説明や例題と違う問題が出たりすると、止まってしまう。

3ヶ月目

ちょっと授業が遅れかけてますと言われてから超特急で進めていく。カウンセリングのたびに間に合いますかとチューターさんに質問して、辟易させる。笑。

4〜5ヶ月目

勉強方法や、カウンセリングの依頼の仕方や、利用方法がわかってきたので順調に進む。自分の勉強は自分なりに進めるしか方法はない。


はじめに は長いので、読み飛ばしていただいても大丈夫です。

はじめに

どうしてオバさんが、AIアプリ開発などという事に興味を持ったのか。

オバさんはグラフィックデザインに仕事で携わり、途中、アナログ作業からMACによるデジタル作業への移行という奔流に流されてAdobe Illustrator や Photoshop、その他のアプリを現場で覚えました。さらにIphoneやAndroid などスマフォの登場でデジタル環境が大きく変化していき、この先どう変わっていくだろう?そう考え、この挑戦に踏み切りました。HPのレイアウト部分はAdobeソフトでなんとか作れますが、組み込まれるプログラミングは難易度が高く、何回か挑戦しその度に挫折してきました。(友人に作ってもらった、プログラムの並びをいじくってめちゃめちゃにしてしまったことが何度かあります。インデント(字下げ)を不審に思い、「なんでこんなに頭が不揃いなんだ」とか思って、全部左に揃えてしまったりとか。授業で読んで、初めて愕然としました。笑。)

「それにしても、もういい歳なんだから、今からなんでそんなことするの?」と友人にも不思議がられました。いわゆる、これは最後のあがきなのです。

定年間近になるにつれ、何か一つプログラミングができたら、定年後契約社員になっても有利なのではないか?とか、それならやはり今はAIだなあとか、Photoshopでやっている画像の処理なんかも、一瞬でやれてしまうのでは?とか単純に思った事もキッカケの1つです。

さて、2021年4月12日よりカウンセリング開始です。チューターさんと呼ばれる、プログラミングの精鋭のみなさんが、カウンセリングという形の対話できるチャット形式で、できない生徒を引っ張っていってくれます。

本当なら、AIアプリ開発コースは3ヶ月で習得できるとのことでしたが、不安なので6ヶ月と倍の日程を選択。そして給付金申請ができるコースなので申請の手続きを終え、ようやく受講準備が整う…かと思っていたらPCのOSバージョンの問題発生。

手持ちの21インチiMACは前の会社からの払い下げで、2013年版OS X Mavericks ver10.9を使用していました。しかし、どうやらバージョンが古過ぎて、授業に必要なインストール予定の数々のアプリが対応できないとなってしまい、アイデミーさんに相談したところ、仮想空間で作業するので、最低Chrombookがあればいいですよということだったので、初回カウンセリングの始まる2日前にアタフタとヨドバシに買いに走り、とりあえず、最初の環境設定を整え授業にのぞみました。勉強はWEBブラウザ上で受講できるので特に問題なく過ごし、会社の帰りに、iphoneでもできるなあとか思っていましたが、画面が小さいとやりにくい!

10インチのChrombook、ましてやiphoneではなかなかやりにくい。授業では、チャット用Slack、授業用教科書、メモ用のテキストエディタ、カウンセリング予約用のTimeRexなどなど、その都度必要なアプリやブラウザを立ち上げながら進めていくので、小さいモニタではやりにくいー。イラチなオバさんは考えました。作業はブラウザとかテキスト主体だからメモリ負担少ないから21インチのi MACのバージョンアップで使えるかも。(この辺は一か八かですよ。場合によっては動きが極端に悪くなる可能性ありなので)MACをOS Sierra10.12.6にバージョンアップ。大当たりー。とりあえず、最後まで進めることができました。後の環境設定カウンセリングでバージョンアップ後のMACの方にもアプリ類インストールできたので、バッチリです。さあ、授業開始です。

授業の概要

★ AIアプリ開発コース6ヶ月のシラバス(スケジュール)
1.Python入門    2.NumPy    3.Pandas   4.Matplotlib   5.データクレンジング  6.機械学習概論    7.教師あり学習   8.スクレイピング入門   9.ディープラーニング基礎   10.CNN概論   11.男女識別   12.HTML&CSS入門   13.Flask入門   14.MNIST   15.アプリ制作   16.コマンドライン入門   17.Git入門   18.Herokuへのデプロイ方法   19.成果物作成(ブログ)

★ 開発環境 
i MAC 2013年版 OS Mavericks-ver10.9 を Sierra-ver.10.12.6にUP   Python2、Colaboratory、Visual Studio Code2、ターミナル

★ 授業-演習問題-添削問題 ★                   1〜19までのコース授業を受けていきます。1.Python入門は57コマ、2.NumPyは30コマというように、コースごとにコマ数は違っています。1コマにつき1つの演習問題が出るので、それに答えていき学習を深めていきます。1コースの終わりに添削問題という総合問題が出るのでそれを提出すると1コースクリアとなります。

★ AIアプリ開発 ★                        AIアプリ開発コースをクリアすると、6ヶ月申請していて、まだ日数が残っている場合は、他の授業を受けることもできます。


AIアプリ【 黒猫と白猫の識別 】を作成する

軸となる画像識別の方法

今回作成したAIアプリは画像識別を主体にしたものなので、

1. CNN (畳み込みニューラルネットワーク)と呼ばれる、画像認識に広く使われるディープニューラルネットワークを使用。CNNの代表的な学習モデルにはLeNet、AlexNet、GoogLeNet、ResNetなどがあり、VGGもその中の1つで、2014年のILSVRCで2位になった、オックスフォード大学のVGGチームの作成したネットワークです。

2. ライブラリtensorflow.kerasよりデータを読み込み、前述のVgg16という16層からなるCNN学習済みモデルを使って転移学習させます。

3. 学習済み画像を一枚受け取り、黒猫か白猫かを判定する為、pred_gender関数に写真を渡し結果を表示させます。

ここから具体例です。仮装環境Google Colaboratoryのdriveにて作業開始。

AIアプリ【 黒猫と白猫の識別 】

作成したWEBページはこちら https://cat-color-endo.herokuapp.com/

オバさんは物覚えが悪いので、実行コードの上に、そのコードの意味や動きを、コメントとして書いていってます。

1.学習用データ黒猫、白猫それぞれの画像のスクレイピング(収集)

pip install icrawler

#黒猫画像データの収集
# Bing用クローラーのモジュールをインポート
from icrawler.builtin import BingImageCrawler

# Bing用クローラーの生成
bing_crawler = BingImageCrawler(
   downloader_threads=4,           # ダウンローダーのスレッド数
   storage={'root_dir': 'images'}) # ダウンロード先のディレクトリ名

# クロール(キーワード検索による画像収集)の実行
bing_crawler.crawl(
   keyword="blackcat 黒ネコ 黒猫 くろねこ",   # 検索キーワード(日本語もOK)
   max_num=300)                    # ダウンロードする画像の最大枚数
   

 #白猫画像データの収集 from icrawler.builtin import BingImageCrawler

bing_crawler = BingImageCrawler(
   downloader_threads=4, 
   storage={'root_dir': 'images2'})

bing_crawler.crawl(
   keyword="whitecat 白ネコ しろねこ 白猫",   # 検索キーワード(日本語もOK)
   max_num=300)                    

こんな画像が集まりました。黒白それぞれ、約300枚。

画像3

画像4

画像6

画像5

2.画像データセットのダウンロード Colaboratory  の drive に収集

集まった画像の中から、イラストや関係ない画像を確認し手作業で削除。300枚指定収集で最終200枚程度になった。

import urllib.request
import zipfile
import os

# URLを指定
url = "https://storage.googleapis.com/tutor-contents-dataset/4050_cleansing_data.zip"
save_name = url.split('/')[-1]

# ダウンロードする
mem = urllib.request.urlopen(url).read()

# ファイルへ保存
with open(save_name, mode='wb') as f:
   f.write(mem)

# zipファイルをカレントディレクトリに展開する
zfile = zipfile.ZipFile(save_name)
zfile.extractall('.')

3.画像データの水増し

初めのコード実行

from PIL import Image
import numpy as np
import cv2

nums = np.arange(100)
for num in nums:
 try:
   im = np.array(Image.open('drive/MyDrive/bcat/blackcat/' + str("{0:06d}".format(num)) + '.jpg'),np.uint8)

   # 左右反転
   def horizontal_flip(image):
       image = image[:, ::-1]
       return image

   l = horizontal_flip(im)
   pil_img = Image.fromarray(l)
   pil_img.save('drive/MyDrive/bcat/blackcatA/' + str("{0:06d}".format(num)) + '.jpg')

   # 上下逆さま
   def vertical_flip(image):
     image = image[::-1, :]
     return image

   m = vertical_flip(im)
   pil_img = Image.fromarray(m)
   pil_img.save('drive/MyDrive/bcat/blackcatB/' + str("{0:06d}".format(num)) + '.jpg')

   # グレー
   def gray(image):
     if(len(image.shape)<3):
       return image
     elif len(image.shape)==3:
       image = cv2.cvtColor(image.astype(np.uint8), cv2.COLOR_RGB2GRAY)
       return image
     else:
       raise

   n = gray(im)
   pil_img = Image.fromarray(n)
   pil_img.save('drive/MyDrive/bcat/blackcatC/' + str("{0:06d}".format(num)) + '.jpg')


   # 輝度値のベースを50上げる
   def right(image):
     image = im + 50 
     return image

   o = right(im)
   pil_img = Image.fromarray(o)
   pil_img.save('drive/MyDrive/bcat/blackcatD/' + str("{0:06d}".format(num)) + '.jpg')

   # ぼかし
   def blur(image):
     image = cv2.GaussianBlur(image, (5, 5), 0)
     return image

   p = blur(im)
   pil_img = Image.fromarray(p)
   pil_img.save('drive/MyDrive/bcat/blackcatE/' + str("{0:06d}".format(num)) + '.jpg')  

   # 元の画像と同じ画像
   def keep(image):
     image = image
     return image

   q = keep(im)
   pil_img = Image.fromarray(q)
   pil_img.save('drive/MyDrive/bcat/blackcatF/' + str("{0:06d}".format(num)) + '.jpg')

 except FileNotFoundError:
   continue

4行目のnums = np.arange( )の( )内を試しに10で実行、問題なかったので100に変更し再実行。さらにblackcatではA〜Fのフォルダを手作業で作成しましたがwhitecatA〜Fは以下のコードを各水増し方法の前に加え実行しました。

if not os.path.exists('drive/MyDrive/whitecatF'):
   # ディレクトリが存在しない場合、ディレクトリを作成する
   os.makedirs('drive/MyDrive/whitecatF')

写真が黒猫か白猫かを判定するために、ライブラリtensorflow.kerasからデータを取り込み、CNNの識別モデルVGG16を用いて転移学習を行います。

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.layers import Dense, Dropout, Flatten, Input
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras import optimizers


# jupyter_contentsディレクトリで
# $ jupyter notebook
# としてjupyterを起動した場合、以下でファイルパスの取得ができます。
path_bcat = os.listdir('drive/MyDrive/bcat/')
path_wcat = os.listdir('drive/MyDrive/wcat/')
# print(path_bcat)
img_bcat = []
img_wcat = []

for i in range(1,len(path_bcat)):
 pic_bcats = os.listdir('drive/MyDrive/bcat/'+path_bcat[i])
 # print(pic_bcats)
 for j in range(len(pic_bcats)):
   img = cv2.imread('drive/MyDrive/bcat/'+path_bcat[i]+'/'+pic_bcats[j])
   img = cv2.resize(img,(50,50))
   img_bcat.append(img)

for i in range(1,len(path_wcat)):
 pic_wcats = os.listdir('drive/MyDrive/wcat/'+path_wcat[i])
 # print(pic_wcats)
 for j in range(len(pic_wcats)):
   img = cv2.imread('drive/MyDrive/wcat/'+path_wcat[i]+'/'+pic_wcats[j])
   img = cv2.resize(img,(50,50))
   img_wcat.append(img)
# for i in range(len(path_wcat)):
#     img = cv2.imread('drive/MyDrive/wcat/' + path_wcat[i])
#     img = cv2.resize(img, (50,50))
#     img_wcat.append(img)
   
X = np.array(img_bcat + img_wcat)
y = np.array([0]*len(img_bcat) + [1]*len(img_wcat))

rand_index = np.random.permutation(np.arange(len(X)))
X_train = X[rand_index]
y_train = y[rand_index]


# 正解ラベルをone-hotの形にします
y_train = to_categorical(y_train)

# モデルにvggを使います
input_tensor = Input(shape=(50, 50, 3))

vgg16=VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
# vggのoutputを受け取り、2クラス分類する層を定義します
# その際中間層を下のようにいくつか入れると精度が上がります
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(2, activation='softmax'))

# vggと、top_modelを連結します
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))

# vggの層の重みを変更不能にします
for layer in model.layers[:19]:
   layer.trainable = False

# コンパイルします
model.compile(loss='categorical_crossentropy',
             optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
             metrics=['accuracy'])

# 学習を行います
model.fit(X_train, y_train, batch_size=100, epochs=10,verbose=1)

pred_gender関数で黒猫か白猫かの判定テストを行いました。      黒猫なら bcat 白猫なら wcat と表示されます。

黒  猫

# 画像を一枚受け取り、黒猫か白猫かを判定する関数
def pred_gender(img):
   img = cv2.resize(img, (50, 50))
   pred = np.argmax(model.predict(np.array([img])))
   if pred == 0:
       return 'bcat'
   else:
       return 'wcat'

# pred_gender関数に写真を渡して黒白を予測します
for i in range(1,10):
 pic_bcats = os.listdir('drive/MyDrive/bcat2/')
 # print(pic_bcats)
 # for j in range(len(pic_bcats)):
 img = cv2.imread('drive/MyDrive/bcat2/'+pic_bcats[i])
 b,g,r=cv2.split(img)
 img = cv2.merge([r,g,b])
 plt.imshow(img)
 plt.show()
 print(pred_gender(img))

判定結果の1例

画像5

bcat 正解


画像6

bcat 正解



白 猫

# pred_gender関数に写真を渡して黒白を予測します
for i in range(1,10):
 pic_wcats = os.listdir('drive/MyDrive/wcat2/')
 # print(pic_bcats)
 # for j in range(len(pic_bcats)):
 img = cv2.imread('drive/MyDrive/wcat2/'+pic_wcats[i])
 b,g,r=cv2.split(img)
 img = cv2.merge([r,g,b])
 plt.imshow(img)
 plt.show()
 print(pred_gender(img))

判定結果の1例

画像8

wcat 正解


画像8

bcat 誤判定


誤判定が出た。白っぽい画面なのに。

とまあ、こんな感じで判定結果を確認しました。正解率は黒猫の方が高かったです。

 #resultsディレクトリを作成 
from google.colab import files
result_dir = 'results'
if not os.path.exists(result_dir):
   os.mkdir(result_dir)
# 重みを保存
model.save(os.path.join(result_dir, 'model.h5'))

files.download( '/content/results/model.h5' ) 

最後に作成したモデルデータを保存して、Herokuサイトにアップロード。

作成したWEBページはこちら https://cat-color-endo.herokuapp.com/

実際に、手持ちの画像をアップロードし、試してみるとうまく判定できました。AIアプリを掲載したWEBページの完成です。

今後の活用

画像の切り抜き作業を自動でできたりすると、とても便利なので、そちらも勉強したいと思います。どうしたらできるかはわかりませんが。そして、E検定は無理でも、G検定など資格の取得も考えられればいいと思っています。すっごくできる方は、資格無しでも自分がやれる事を知っているので、全然必要ないと思うのですが、やはり、なんちゃっての人間は、資格取得したという事実が社会でものを言いますので。

アイデミー主催者さま

受講生にとってはカウンセリングは重要ですが、大事な局面で聞けないと不安だから、とっておきたくなります。でも、本当はもっと質問したい。そういう意味ではorviceは有効ですが、時間が15分なので微妙です。カウンセリングのコマ数が減っていくと不安にもなりますし、もし可能なら、カウンセリングのコマを購入できるとか、何か他の方法があれば嬉しいかもしれません。あまり費用がかかるのも痛手ですが。

おわりに

ご指導いただいたチューターの皆さん、本当にありがとうございました。オバさんここまでこれました。今後はこの学習経験を元に、AIについての理解をもっと深めたいと思います。

こんなブログを読んでいただいた方にも、お礼申し上げます。これからプログラミングを学ぼうと思われる方にも、何かの一助になれば幸いです。  こんな、ど素人のオバさんができるなら、貴方もできます。この勉強中にも世間ではコロナの暴風が吹き荒れ、オバさんはじめ周りの人間もワクチン接種へ走っております。軽い認知症の母にもチャット中、幾度か踏み込まれ(1部のチューターさんはご存知かと。笑。)人生は1つのことをやろうとしても、周りに振り回されて、なかなか1本道を進むことはできません。(確信です)それでもめげず、逆に笑って楽しめるように強い心を育んで、たくさんの事を吸収してください。

長い間、お付き合いいただき、ありがとうございました。




この記事が気に入ったらサポートをしてみませんか?