Kaggle チャレンジ

正月なまりを吹っ飛ばすべく、今回はKaggleチャレンジをします。

Kaggleとは

世界中のデータサイエンティスト達がデータ分析の腕を競い合うプラットフォームです。企業や研究者が提供するデータセットに対し、適切な予測モデルを構築しその予測精度を競います。上位入賞者には賞金が出ます。
様々なデータセットが手に入り、他の競技者の解説(カーネル)を見ることができるので、データ分析の勉強にも非常に有用です。

Kaggleを始める方法

  1. Kaggleのサイトに接続してアカウントを作成します。
  2. Jupyter Notebook(Webブラウザで動作するpythonの対話環境)をインストールします。
  3. コンペに参加

これだけです!

住宅価格予測

今回は、Kaggleの回帰問題のチュートリアルである「House Prices: Advanced Regression Techniques」をやってみます。(cybozu02さんのカーネルを参考しております)

www.kaggle.com

1. ライブラリの準備

今回使用するライブラリをインポートします。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import PowerTransformer
  • numpy: 数値計算を効率的に行うための拡張モジュール
  • pandas: データ解析を支援する機能を提供するライブラリ
  • matplotlib: グラフ描画ライブラリ
  • seaborn: 可視化ライブラリ
  • PowerTransformer: 0や負値を含んだ変数も対数変換ができるライブラリ
2. データの読み込み

こちらのリンクから以下のデータセットをダウンロードして読み込みます。

  • train.csv: 学習データ
  • test.csv: テストデータ
#pandasを使用してcsvデータ読み込み
train = pd.read_csv("train.csv")
test_x = pd.read_csv("test.csv")

#学習データの特徴量を出力
train.columns

f:id:KenjiU:20200114235255p:plain

学習データの特徴量は79個あります。

  • MSSubClass: 住居のタイプ
  • MSZoning: 住居のゾーン
  • LotFrontage: 隣接した道路の長さ
  • LotArea: 敷地面積
  • Street: 道路のタイプ
  • Alley: 路地のタイプ
  • LotShape: 土地の形状
  • LandContour: 土地の平坦さ
  • Utilities: ガス・電気・水の利用
  • LotConfig: 土地の構成
  • LandSlope:土地の傾斜
  • Neighborhood: 近所

等です。
実践さながらのデータでわくわくしてきますね!

3. データ分析

まずは、予測対象の変数(目的変数)である「SalesPrice(住宅価格)」について確認します。

plt.hist(train_saleprice, bins=100)
plt.show()

f:id:KenjiU:20200114235813p:plain

左に偏っており正規分布になっていません。機械学習において目的変数が正規分布に従ったほうが精度が良くなる、ということが知られているので後ほど正規分布に変換します。

次に、特徴量を確認します。

  • TotalBsmtSF: 地下室の広さ
  • 1stFlrSF: 1階の広さ
  • GrLivArea: リビングの広さ
  • GarageArea: 車庫の広さ
  • LotArea: 土地の広さ

の広さが、住宅価格に影響するのでは、と考えます。
相関関係を見てみましょう。

#地下室の広さと住宅価格の散布図を作成
data = pd.concat([train["TotalBsmtSF"],train["SalePrice"]],axis=1)
plt.figure(figsize=(20, 10))
plt.scatter(train["TotalBsmtSF"],train["SalePrice"])
plt.xlabel("TotalBsmtSF")
plt.ylabel("SalePrice")

#1階の広さと住宅価格の散布図を作成
data = pd.concat([train["1stFlrSF"],train["SalePrice"]],axis=1)
plt.figure(figsize=(20, 10))
plt.scatter(train["1stFlrSF"],train["SalePrice"])
plt.xlabel("1stFlrSF")
plt.ylabel("SalePrice")

#リビングの広さと住宅価格の散布図を作成
data = pd.concat([train["GrLivArea"],train["SalePrice"]],axis=1)
plt.figure(figsize=(20, 10))
plt.scatter(train["GrLivArea"],train["SalePrice"])
plt.xlabel("GrLivArea")
plt.ylabel("SalePrice")

#車庫の広さと住宅価格の散布図を作成
data = pd.concat([train["GarageArea"],train["SalePrice"]],axis=1)
plt.figure(figsize=(20, 10))
plt.scatter(train["GarageArea"],train["SalePrice"])
plt.xlabel("GarageArea")
plt.ylabel("SalePrice")

#土地の広さと住宅価格の散布図を作成
data = pd.concat([train["LotArea"],train["SalePrice"]],axis=1)
plt.figure(figsize=(20, 10))
plt.scatter(train["LotArea"],train["SalePrice"])
plt.xlabel("LotArea")
plt.ylabel("SalePrice")

f:id:KenjiU:20200115000607p:plain f:id:KenjiU:20200115000613p:plain f:id:KenjiU:20200115000628p:plain f:id:KenjiU:20200115000632p:plain f:id:KenjiU:20200115000647p:plain

広くなるにつれて住宅価格が上昇する傾向が見られますね。外れ値がいくつかあるので除外しておきます。

#外れ値を除外
train = train.drop(train[(train['TotalBsmtSF']>6000) & (train['SalePrice']<200000)].index)
train = train.drop(train[(train['1stFlrSF']>4000) & (train['SalePrice']<200000)].index)
train = train.drop(train[(train['GrLivArea']>4000) & (train['SalePrice']<200000)].index)
train = train.drop(train[(train['GarageArea']>1200) & (train['SalePrice']<300000)].index)
train = train.drop(train[(train['LotArea']>80000) & (train['SalePrice']<400000)].index)
4. 特徴量の作成

より良い特徴量を作成する特徴量エンジニアリングを進めていきます。

目的変数(住宅価格)を学習データから切り出します。また、学習データとテストデータをまとめて処理するため一旦マージしておきます。

#学習データを目的変数(住宅価格)とそれ以外に分ける
train_x = train.drop("SalePrice",axis=1)
train_y = train["SalePrice"]

#学習データとテストデータをマージ
all_data = pd.concat([train_x,test_x],axis=0,sort=True)

#IDのカラムは学習に不要なので別の変数に格納
train_ID = train['Id']
test_ID = test_x['Id']

all_data.drop("Id", axis = 1, inplace = True)
5. 欠損値の処理

分析に利用するデータには多くの場合、何らかの理由により記録されなかった値、欠損値が含まれます。欠損値があると統計処理ができなくなるので、削除や0埋め等が必要です。まずは欠損値がどのくらいあるのかを確認します。

#データの欠損値
all_data_na = all_data.isnull().sum()[all_data.isnull().sum()>0].sort_values(ascending=False)

#欠損値の数をグラフ化
plt.figure(figsize=(20,10))
plt.xticks(rotation='90')
sns.barplot(x=all_data_na.index, y=all_data_na)

#欠損値があるカラムをリスト化
na_col_list = all_data.isnull().sum()[all_data.isnull().sum()>0].index.tolist()
all_data[na_col_list].dtypes.sort_values()

f:id:KenjiU:20200115002401p:plain

  • PoolQC: プールの質を表す。プールがない場合にはNAとなる。
  • MiscFeature: 備え付けられている特別な設備(エレベータ等)を表す。何もない場合はNAとなる。
  • Alley: 物件にアクセスするための路地のタイプを表す。該当しない場合はNAとなる。
  • Fence: 敷地などを仕切る囲いの質を表す。囲いがない場合はNAとなる。
  • FireplaceQu: 暖炉の質を表す。暖炉がない場合はNAとなる。

が多く欠損しています。
対象物そのものが存在しない場合、欠損として扱われているようです。

  • float型の場合は「0」
  • object型の場合は「None」

で置換することにしましょう。

物件に隣接した道路の長さ(LotFrontage)については平均値で穴埋めします。

#物件に隣接した道路の長さ(LotFrontage)の欠損値を平均値で穴埋め
all_data['LotFrontage'] = all_data['LotFrontage'].fillna(all_data['LotFrontage'].median())

#欠損値が存在する、かつfloat型の場合は「0」で置換
float_list = all_data[na_col_list].dtypes[all_data[na_col_list].dtypes == "float64"].index.tolist()
all_data[float_list] = all_data[float_list].fillna(0)

#欠損値が存在する、かつobject型の場合は「None」で置換
obj_list = all_data[na_col_list].dtypes[all_data[na_col_list].dtypes == "object"].index.tolist()
all_data[obj_list] = all_data[obj_list].fillna("None")
6. 数値変数の処理
  • MSSubClass: 住宅の種類
  • YrSold: 販売年
  • MoSold: 販売月

については、数値ですが、数や量で測れない変数なので、カテゴリ変数として扱うことにします。

#カテゴリ変数に変換する
all_data['MSSubClass'] = all_data['MSSubClass'].apply(str)
all_data['YrSold'] = all_data['YrSold'].astype(str)
all_data['MoSold'] = all_data['MoSold'].astype(str)
7. 目的変数を対数変換

目的変数(住宅価格)が正規分布になっていないため、対数変換をすることで正規分布にします。

#目的変数を対数変換する
train_y = np.log1p(train_y)

#可視化
plt.figure(figsize=(20, 10))
sns.distplot(train_y)

f:id:KenjiU:20200115003749p:plain

8. 説明変数を対数変換

説明変数についても正規分布になっていない(歪度が0.5よりも大きい)ものは対数変換していきます。0や負値を含んだ変数も対数変換ができる「Yeo-Johnson変換」を使用します。

#数値の説明変数のリスト
num_feats = all_data.dtypes[all_data.dtypes != "object" ].index

#各説明変数の歪度を計算
skewed_feats = all_data[num_feats].apply(lambda x: x.skew()).sort_values(ascending = False)

#歪度の絶対値が0.5より大きい変数だけに絞る
skewed_feats_over = skewed_feats[abs(skewed_feats) > 0.5].index

#Yeo-Johnson変換
pt = PowerTransformer()
pt.fit(all_data[skewed_feats_over])

#変換後のデータで各列を置換
all_data[skewed_feats_over] = pt.transform(all_data[skewed_feats_over])
9. 特徴量の追加

新しい特徴量を追加することで、予測モデルの性能が向上することがあります。以下の特徴量を追加します。

#プールの有無(広さが0より大きい場合は有)
all_data['haspool'] = all_data['PoolArea'].apply(lambda x: 1 if x > 0 else 0)

#2階の有無(広さが0より大きい場合は有)
all_data['has2ndfloor'] = all_data['2ndFlrSF'].apply(lambda x: 1 if x > 0 else 0)

#ガレージの有無(広さが0より大きい場合は有)
all_data['hasgarage'] = all_data['GarageArea'].apply(lambda x: 1 if x > 0 else 0)

#地下室の有無(広さが0より大きい場合は有)
all_data['hasbsmt'] = all_data['TotalBsmtSF'].apply(lambda x: 1 if x > 0 else 0)

#暖炉の有無
all_data['hasfireplace'] = all_data['Fireplaces'].apply(lambda x: 1 if x > 0 else 0)
10. カテゴリ変数の処理

カテゴリ変数を、One-Hotエンコーディングにより「0」と「1」だけの数列に変換します。

#カテゴリ変数となっているカラム
cal_list = all_data.dtypes[all_data.dtypes=="object"].index.tolist()

#pandasのget_dummies関数でOne-Hotエンコーディング
all_data = pd.get_dummies(all_data,columns=cal_list)
11. データの分割

マージした学習データとテストデータを再度分割します。

#学習データとテストデータに再分割
train_x = all_data.iloc[:train_x.shape[0],:].reset_index(drop=True)
test_x = all_data.iloc[train_x.shape[0]:,:].reset_index(drop=True)
12. 予測モデルの作成&実行

勾配ブースティング(アンサンブル学習と決定木を組み合わせた手法)のライブラリ「XGBoost」でモデルを作成します。

  • max_depth: 木の深さの最大値
  • eta: 学習率を調整
  • objective: 損失関数を指定

等のハイパーパラメータについて、設定値を色々試してみたいですね。

from sklearn.ensemble import RandomForestRegressor,  GradientBoostingRegressor
from sklearn.model_selection import KFold, cross_val_score, train_test_split
from sklearn.metrics import mean_squared_error
import xgboost as xgb
from sklearn.model_selection import GridSearchCV

#データの分割
train_x, valid_x, train_y, valid_y = train_test_split(
        train_x,
        train_y,
        test_size=0.3,
        random_state=0)

#特徴量と目的変数をxgboostのデータ構造に変換する
dtrain = xgb.DMatrix(train_x, label=train_y)
dvalid = xgb.DMatrix(valid_x,label=valid_y)

#パラメータを指定して勾配ブースティング
num_round = 5000
evallist = [(dvalid, 'eval'), (dtrain, 'train')]

evals_result = {}

#パラメータ
param = {
    'max_depth': 3,
    'eta': 0.01,
    'objective': 'reg:squarederror',
}

#学習の実行
bst = xgb.train(
    param, dtrain,
    num_round,
    evallist,
    evals_result=evals_result,
)    
#学習曲線を可視化する
plt.figure(figsize=(20, 10))
train_metric = evals_result['train']['rmse']
plt.plot(train_metric, label='train rmse')
eval_metric = evals_result['eval']['rmse']
plt.plot(eval_metric, label='eval rmse')
plt.grid()
plt.legend()
plt.xlabel('rounds')
plt.ylabel('rmse')
plt.ylim(0, 0.3)
plt.show()

f:id:KenjiU:20200115012809p:plain

13. 提出用csvファイルの作成

いよいよ最後です。予測結果をcsvファイルに出力します。予測結果のSalePrice(住宅価格)は対数をとった値なので、Exponentialをかけてあげる必要があります。

#予測結果を出力
dtest = xgb.DMatrix(test_x)
my_submission = pd.DataFrame()
my_submission["Id"] = test_ID
my_submission["SalePrice"] = np.exp(bst.predict(dtest))
my_submission.to_csv('submission.csv', index=False)

f:id:KenjiU:20200115015847p:plain

1998位/5343人でした!

以下は今回参考にさせていただいたcybozu02さんのカーネルです。ありがとうございました。 www.kaggle.com

ふるさと 会津

明けましておめでとうございます。新年も幸多き年でありますよう心よりお祈り申し上げます。本年もどうぞよろしくお願いいたします。

今回は僕のふるさとの福島県会津について少しご紹介いたします。

会津の場所

f:id:KenjiU:20200104171405p:plain
福島県 会津地方
福島県は「会津」「中通り」「浜通り」の3つの地域に分かれていて、会津は西側です。
福島県内では「あづ」と、「い」にアクセントをおきます。
エンヤーあ磐梯山は 宝の山よ〜♪

会津の冬

f:id:KenjiU:20200104172948j:plain
只見線
会津の冬は豪雪で、雪だるま・かまくら作り、雪合戦、つららチャンバラなど何でもやりたい放題です。僕の出身は喜多方ラーメン喜多方市なのですが、小学校の校庭には山があり、冬はスキーを履いて滑りながら登校、体育の時間にその山でスキーをしていました。祖母の家は山奥で、雪が2m以上積もることもあり、家の2階から出入りもできました。屋根からの雪ダイブは最高です。
会津福島県の山間地にあり県内で過疎化がもっとも懸念されている地域でもあります。

会津若松市

f:id:KenjiU:20200104173111j:plain
鶴ヶ城
会津の中心都市は「会津若松市」です。人口は約12万人。
江戸時代には会津藩の城下町として盛え、2013年のNHK大河ドラマ「八重の桜」の舞台にもなりました。主演の綾瀬はるかさんは毎年「会津まつり」に参加しています。

会津若松市には公立大学の「会津大学」があります。1993年に日本初のコンピュータ専門大学として開設され、現在はコンピュータ理工学部・コンピュータ理工学科の一学部一学科で構成されます。 www.u-aizu.ac.jp AIセンターも設置され、AIの研究・人材育成にも力を入れています。

また、会津若松市では、IoT、AI、ビッグデータなどのさまざまな技術を活用して、人々のより良い生活を可能とする都市を実現しよう、という「スマートシティ」構想を進めています。 www4.pref.fukushima.jp 2019年の4月に「スマートシティAiCT」がオープンしました。大手企業も入居しています。地元・入居企業、会津大学会津若松市の「産学官連携」による新たなイノベーションを生み出すことが期待されます。
ぜひ、会津だけで閉じることなく、日本全国に広げることができるモデル都市になって欲しいです。

BRISWELL 2020 Premium

2020年、弊社も
テクノロジーで新しい価値を創造し、より良い社会の実現に貢献する
をミッションに掲げ、色々とチャレンジしていきます!
よろしくお願いいたします。

2019年のAI振り返り

コーンフレークが食べたくなる今日この頃。
今年も残すところあとわずかとなりました。あっという間でしたね!

さて、今年一年AI分野で多くのニュースがありました。弊社のオフィスでは新聞を取っているのですが、2日に1回は新聞の1面にAI関連の記事が載っていた感じです。

2019年のAIを振り返っていきましょう。

自然言語処理

今年は特に自然言語処理領域の発展が目立ちました。自然言語処理とは「私たち人間が日常書いたり話したりしている言語をコンピュータに処理させる」技術を表します。

例えば
「こーんふれーくがねたりない」
この文は
①コーンフレークが寝足りない
②コーンフレークがね、足りない
の2つの解釈ができます。

人間であれば「コーンフレークは寝ない」と考えるので①ではなく②を選ぶでしょう。ただ、機械はどちらを選んで良いかわかりません。このような自然言語の曖昧さを解消させる技術が発展してきています。

www.itmedia.co.jp

のようにAIが人間の読解力に近づいています。(いや超えていますね...)

また、Googleは2019年10月25日に最新の自然言語処理技術「BERT」を検索エンジンに採用したと発表しました。「BERT」は文脈を理解することができます。

www.blog.google

こちらのGoogleブログに以下のサンプルがあります。

2019 brazil traveler to usa need a visa.

訳は「2019年ブラジル人がアメリカに旅行に行く時ビザは必要か」(ブラジル人→アメリカ)になりますが、以前のGoogleは「to」(→)を理解できず、逆の意味「2019年アメリカ人がブラジルに旅行に行く時ビザは必要か」(アメリカ人→ブラジル)と認識していました。

それが「BERT」を導入することで文脈を正しく理解するようになっています。その結果、これまで文脈を理解されず、検索結果で上位に表示されなかったページが、正しく認識され表示されるようにもなります。(日本の検索エンジンにはまだ導入されていないようです)

ちなみに「自然言語処理」は、弊社Uri&Yuki漫才コンビ「下北ラヴァーズ」でもネタに取り込んでいます。来年の進化に期待です。

画像処理

2019年は画像認識より画像生成の技術が話題になりました。特にディープラーニング技術を応用した「GAN(敵対的生成ネットワーク)」というモデルが注目されました。

GANの仕組みは、美術品の贋作者と鑑定士の関係に例えられます。

贋作者の「Generator」と、贋作を見破ろうとする鑑定士の「Discriminator」という2種類のネットワークから構成されています。Generator(贋作者)は本物にできるだけ近い贋作を作り出し、その贋作をDiscriminator(鑑定士)は見破ります。Discriminator(鑑定士)の見破る能力が上がってくると、Generator(贋作者)もより質の高い贋作を作ります。するとDiscriminator(鑑定士)もまたまた能力を上げて... というのを繰り返し、最終的に本物そっくりのものが作られて
スーパー鑑定士:「これは間違いなく本物です。大切になさってくださいね。」
となるのがGANの仕組みです。

このGANを利用して、実在しないデータを生成したり、存在するデータの特徴に沿って変換ができます。

ウマがリアルタイムでシマウマに変換されます、 これは2つのデータソース間の変換を学習するCycleGANという技術を利用しています。

本物そっくりですね。このような偽造動画はディープフェイクと呼ばれます。 GANによってますますディープフェイクの技術は向上しており、社会問題にもなってきています。

www.kaggle.com

のようにディープフェイク検出がkaggleのコンペにもなっています。
来年は弊社AIチームもkaggleチャレンジ予定です。

AIのツール化

2019年はAI領域ではGUIツールがさらに広まった一年でした。今までは、機械学習モデルを構築したり、データ分析をする場合、プログラミング言語、数学など専門的知識が必要でした。GUIツールでは、プログラミングの記述が不要で、画面操作のみで容易に実行できます。その結果、モデル構築から検証までのスピード・サイクルを早めることもできます。

・サーバー・クラウド 不要!
・専門知識・プログラミング 不要!
・位置設定 不要!
のような、映像を撮影するだけで利用できるAI外観検査ツールも出てきました。

しかし、AI構築が全てツールだけで完結できるわけではありません。解決する課題を見極めたり、必要なデータを収集したり、AI構築するためのリソースはまだとても多いです。

最後に

AI関連の技術のアップデートはとても早く、数年前のものでも古典的な技術になったりします。AI業界で活躍するためには勉強し続けることが大事です。来年もナレッジの蓄積と共有を積極的に行っていきます。

みなさま、良いお年をお迎えください!

nginx リダイレクト記載方法

どうも、こんにちわ。

 

AWS ElasticBeansTalk を使ってとあるPJを進行していたところ、

検索画面で 

検索ボタン押す

結果が表示される

URLバーにカーソル合わせてEnter

 

と押すとなぜか

https://xxx.xxxx.xx/v1/order?orderDateFrom='1111-11-11'

https://xxx.xxxx.xx/v1/order?orderDateFrom='1111-11-11'?orderDateFrom='1111-11-11'

こうなるという... orderDateFrom 君はなぜ2回登場してくるの...

 

Localでは発生しなかったので、EBの nginx.config で記載していた

 

server {
listen 81;
rewrite ^ https://$host$request_uri permanent;

 こいつ怪しくない...??

となりました。

 

Google先生に聞いてみると確かに rewrite より return を使え

みたいなのがちらほらあり、試しに

server {
listen 81;
return 301 https://$host$request_uri;

 に変更したところ発生しなくなった。

 

中々難しいですな... 精進します...

クラスタリング勉強会

昨日は社内でAI勉強会(by 大澤さん)を実施しました。

今回は教師なし学習クラスタリングがテーマでした。コンテンツ・シナリオ・説明の仕方、どれもとても分かりやすく、終始惹きつけられました。「試しにやってみよう!」のコーナーは商品色分類という身近なものを題材にしていてとても興味深いものでした。発表後のディスカッションタイムは今までにないくらい白熱していましたね!

来年は外部向けのAIセミナーも開催する予定です。

ビジネス分野での活用例

クラスタリングは、マーケティングの戦略立案・顧客の特性分け・商品のポジショニング分析などに利用されています。

例えば、購買履歴データを分析してお客様のグループ(価格重視型、健康志向型、新商品重視型 等)を作り、そのグループに対して特別なキャンペーンを実施したり、嗜好に合う商品をリコメンドしたり、することで販売促進のための効果的な施作を打てるようになります。

このようなグルーピングをAI(機械学習)の力で行い、新たな気付きを得ることがクラスター分析の魅力です。

医療分野での活用例

最近はどのような分野・用途で利用されているのかな、と色々調べていたところ

昨日のニュース記事

今回研究グループは、複数のディープラーニングと非階層型クラスタリングを用いることで、病理画像から人間が理解できる情報を自動で取得する新たなAI技術の開発に成功。医療分野では今まで、医師が教えた診断をAIが学習する、すなわち教師以上の分類はできない「教師あり学習」が主に使用されてきたが、今回の研究では医師の診断を必要としない「教師なし学習」により獲得した特徴を、人間が理解できるように変換。再発期間のみを用いた最適な重み付けをAIに行わせることで、これまで不可能であったがんの未知なる情報の獲得を目指した。
引用:QLifePro | がんの特徴をAIが自力で獲得、再発診断精度を向上する新たな特徴も発見-理研ほか

のように、医療分野での利用も進められているようです。

AIが人間の理解を深める情報を提供する、さらに新たな気付きを人間に与えてくれるという、AIと人間が補完しあうとても興味深い技術です。

複数のディープラーニングと非階層型クラスタリングを用いる

についてどのようなアルゴリズムが使われているのか気になったので、論文を確認しました。

We then applied a deep autoencoder we had developed for pathology images (Supplementary Fig. 2) to 128 × 128-pixel image patches, clustering the 2048 intermediate-layers to form 100 features (clusters) by k-means clustering.
引用:Nature Communications | Automated acquisition of explainable knowledge from unannotated histopathology images

ディープオートエンコーダで次元圧縮をして、100個のクラスタ数にk-meansのアルゴリズムクラスタリングしているようです。
(「次元圧縮」と「k-meams」は大澤さんの勉強会にも出てきました!)

最後に

AIのアルゴリズムは色々あります。 難しそうな名前のアルゴリズムもその中身を知れば、自分が対象とする問題に適用可能かの判断もできます。 そして、絞り込んだアルゴリズムに対して、問題やデータの特性を見抜くことで実際に使用するアルゴリズムを選択することができるようになります。

理解を深めるために、実際にプログラミングをしてアルゴリズムに触れるのも大事です。
来年予定しているAIセミナーは、ハンズオンも取り込んでいきたいですね。

ブリスウェル ベトナムへの移動方法( NRT -> SGN )

こんにちは。宇佐美です。弊社子会社であるブリスウェル ベトナムへ出張中です。
ベトナムオフィスへの行程をまとめます。
技術とは関係ありませんが、ブリスウェル ベトナム訪問の際の移動時間や費用のベンチマークとしてお役に立てれば幸いです!

フライト

ベトナム航空 (NRT)→(SGN)

  • 2時間前にチェックイン。空席は真ん中の席のみ。
  • 定刻50分前に搭乗口集合。(離陸は定刻20~30分後。)
  • フライト中のMacBook Pro 15inchの使用&充電は禁止と機内放送あり。
  • 機内のディスプレイ不具合で度々操作不能
    • 不具合は周りの5~6席でも発生
    • 解消には電源マーク長押しで再起動 & 5分ほど待つ必要あり。
  • タンソンニャット国際空港(SGN)着陸は到着予定時刻通り。
  • 入国審査通過まで約40分ほど。

両替

直接ホテルへ向かう予定だったので空港内で両替しました。
ググって評判のよい No.5 "EXIMBANK" と記載がある両替所を利用。
レシートも貰えて1 円 = 210.1 ドンで両替しました。
(当日は1円 = 212ドンぐらいのレートだったタイミングでした。)

空港内の両替所でも、レシートなしでいくらか抜かれていたり計算時に数%レートを落とすところもあるようですのでお気をつけください。
No.5の両替所では機械で枚数を数えた紙幣を渡してもらえました。

空港タクシー乗り場

タクシーはボッタクられる場合があるので、評判が良いビナサンタクシーを目指します。

空港到着口を出たら左に突き進みます。
TAXI STANDと記載があるので、深緑色のシャツを着た人がビナサンの係員です。

他の会社の係員も"イエス!ビナサン!"と言いつつ乗せようとするのでお気をつけください。
(当のビナサンの係員はその様子を微笑みながら見守るだけでした。)

空港からブリスウェル ベトナム

空港から20~30分ほど。120,000ドン(=500~600円ほど)で到着です。
なお、タクシーが空港を出る際に料金が10,000ドンかかります。
私は最後の精算時に合わせて請求でしたが、空港で請求されることもあるようです。 

その他 (Grab)

タクシー以外にもGrabというUberのようなサービスもあります。
乗用車かバイクを選べてタクシーより安いです。
スーツケース有りの利用者を見かけたので次回チャレンジしてみたいです。

f:id:usami-t:20191220004522j:plain

スーツケース+ネックピロー+Grab

以上です。

OpenCVで出来ること

Pythonで画像や動画の処理をする時に良く使うのがOpenCVというライブラリです。

弊社でも最近

等で使用しています。

今回のブログでは、OpenCVでどんなことが出来るのかを紹介していきます。

弊社の中で
「ナレッジの蓄積と共有を積極的に行っていこう!」
という機運も高まっており、今後もこのような感じで発信を続けていきたいと思います。
よろしくお願いします。

OpenCVとは

OpenCVとはオープンソースのコンピュータビジョンライブラリです。コンピュータービジョンとは、コンピュータにデジタルな画像・動画をよく理解させることを意味します。OpenCVはその処理をするための様々な機能があります。

BSDライセンスのため、無料で使うことができ、商用利用も可能となっております。簡単な画像処理はもちろん、顔や文字領域の検出、物体の追跡などの様々な機能が用意されており簡単に扱うことが出来ます。

WindowsmacOSLinuxiOSAndroid 等のマルチな環境をサポートしています。

OpenCVのメリットとは

① インストールがとても簡単

Windowsの場合は、pipコマンド
$ pip install opencv-python
 
macOSの場合は、Homebrewを用いてbrewコマンド
$ brew install opencv
でインストール可能です。

② コードがシンプルですぐに試すことが出来る

いつも僕たちを元気付けてくれる弊社の取締役(陽治郎さん)をグレースケール化したい場合

f:id:KenjiU:20191214184005j:plain
yojiro-original.jpg
コードは以下になります。

import cv2

img = cv2.imread('yojiro-original.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
cv2.imwrite('yojiro-gray.jpg',gray)

以下のように変換されます。(掲載許可はいただいております!)
とても簡単ですね。

f:id:KenjiU:20191214184226j:plain
yojiro-gray.jpg

③ 画像解析の前処理が出来る

画像解析は、前処理がとても効果的です。
前処理とは、手元にあるデータを解析する前に、何らかの加工を施すこと。
そうすることで、アルゴリズムが学習しやすくなります。

画像のサイズを統一したり、グレースケール化・コントラスト強調・ノイズ除去等をすることで、より精度の高い機械学習が実行できます。
OpenCVを使えばこのような前処理の作業を簡略化できます。

④ 他のライブラリと組み合わせることが出来る

描画ライブラリのMatplotlibと組み合わせると

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('yojiro-original.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()

以下のようにグラフ描画が出来ます。 f:id:KenjiU:20191214185812p:plain

数値計算ライブラリのNumPyと組み合わせると

import cv2
import numpy as np

gamma = 2
lookUpTable = np.zeros((256, 1), dtype = 'uint8')

for i in range(256):
    lookUpTable[i][0] = 255 * pow(float(i) / 255, 1.0 / gamma)

img_src = cv2.imread('briswell-original.jpg', 1)
img_gamma = cv2.LUT(img_src, lookUpTable)
cv2.imwrite('briswell-contrast.jpg', img_gamma)

加工前

f:id:KenjiU:20191214195321j:plain
briswell-original.jpg

加工後

f:id:KenjiU:20191214195620j:plain
briswell-contrast.jpg

のように暗い部分がはっきりと見えるようになります。

まとめ

今回は、OpenCVとは何か、具体的にどのようなことができるのか、について書きました。
画像処理は目に見えて結果が分かりやすいので、プログラミングを学ぶ上でとっつきやすいのではないでしょうか。
オープンソースなので気軽に利用できるのも嬉しいですね。