Briswell Tech Blog

ブリスウェルのテックブログです

MySQL クエリの小技集

こんにちは、naoyaです。
10月に入り一気に涼しくなり、ここ数年では早く思える秋の訪れを感じます。
僕は春は花粉症で薬が手放せず、夏は暑さが苦手でエアコンに頼りっきりなので涼しい秋の気候が一番好きです。

はじめに

今回のお題はMySQLにおけるクエリについてとなります。
先日、新たにテスターとして参画した社員向けにMySQLのSELECT文などの説明をする機会がありました。
そんな中、普段何気なく使っている関数などが意外と知られていなかったりするのかな、と感じたものがあり今回は改めて応用的なテクニックをまとめてみました。

CASE句

条件に応じて指定の文字列や異なるカラムを1つの列に出力したい時は
CASE WHEN "条件A" THEN '"条件Aの場合の結果"' ELSE '"条件を満たさない場合の結果"' END
で条件に応じた結果を表示することが出来ます。
(WHEN ~ THEN ~ は複数記述可能)
イメージとしてはJavaScriptExcelの関数でも使われるIF文のようなものです。

例、注文(order)テーブルの情報から、「納品状態」を納品日(deliveryDate)が過去なら"納品済"、納品日が未来なら"納品予定"、それ以外(≠日付が入っていない状態)は"納品日未定"と出力する

SELECT id,deliveryDate,
CASE 
WHEN deliveryDate <= CURDATE() THEN '納品済' 
WHEN deliveryDate > CURDATE() THEN '納品予定' 
ELSE '納品日未定' END AS `納品状況` 
FROM `order`


四則演算や四捨五入

カラム同士を+ - * / で繋げることで四則演算が出来ます。

例、注文の明細(orderDetail)の価格(price)と数量(amount)から金額の計算を行う

SELECT price * amount AS `金額` FROM `orderDetail`


TRUNCATE("数値","桁数")
で切り捨てが出来ます。
これを応用することで切り上げ/四捨五入も可能です。
(四捨五入はROUND関数でも近い挙動をするが、厳密には処理内容が異なる)

例、単価 * 数量の金額計算で小数点以下を
切り捨ての場合

SELECT price,amount,TRUNCATE(price * amount,0) AS `金額` FROM `orderDetail`;


切り上げの場合

SELECT price,amount,TRUNCATE(price * amount + 0.9,0) AS `金額` FROM `orderDetail`;

対象の数値に0.9 ※1 を足すことで1の位が繰り上がり、
TRUNCATEで切り捨てることで結果が切り上げと同様の結果になります。※2

※1 対象の数値の小数点以下が1桁までの場合は+0.9、
2桁までの場合は+0.99...と切り上げ処理を行う前の桁数に応じて可変させる

※2 処理前の数値 = 1.2 → 1.2+0.9 = 2.1 → 切り捨てを行い結果は2
処理前の数値 = 1.9 → 1.9+0.9 = 2.8 → 切り捨てを行い結果は2
でどちらも結果は切り上げとなる

四捨五入の場合

SELECT price,amount,TRUNCATE(price * amount + 0.5,0) AS `金額` FROM `orderDetail`;

切り上げとほぼ同じ理屈で0.5を足して1の位が繰り上がるかどうかで四捨五入と同様の結果になります。

LIMIT,OFFSET

LIMITとOFFSETを利用して表示する結果の件数を変更できます。
主に検索結果のページングなどで利用します。

例、注文(order)情報を日付(orderDate)が古い順に50件づつ表示する
1ページ目、100件の内の1~50件目

SELECT * FROM `order`
ORDER BY orderDate
LIMIT 50;


2ページ目、100件の内の51~100件目

SELECT * FROM `order`
ORDER BY orderDate
LIMIT 50
OFFSET 50;

検索結果の"OFFSET+1"件目から"LIMIT"件のレコードを表示する形になります。
(OFFSETは検索結果の先頭から除外する件数、というイメージ)

1:Nの関係から最大値(最小値)と紐づくデータの取得

テーブル同士の連結を行うLEFT JOINを利用して、1:Nで紐づくデータからN側のテーブルの特定のカラムが最大値(最小値)のデータを抽出することが出来ます。

例、顧客(customer)に紐づく注文(order)の中で、最新(order.createdAtが最も未来日の1件)の注文情報を抽出する

SELECT c.id,c.name,o1.id,o1.createdAt FROM `customer` AS c
LEFT JOIN `order` AS o1 ON c.id = o1.customerId
LEFT JOIN `order` AS o2 ON c.id = o2.customerId AND o1.createdAt < o2.createdAt
WHERE
o2.id is null;

o2はo1のレコードより新しいcreatedAtのレコードを探すため、o2に該当するレコードが見つからない(o2.id is nullの)o1のレコードが最新の注文という考え方です。
日付や金額など、比較可能なデータであれば同様に取得可能です。
(比較演算子を逆にすれば最小値も取得可能)

条件付きのUPDATE文

こちらは非常に限定的な使い方をしたので実例に沿って説明します
本番運用中のプロジェクトで一部画面のリスト値に更新が入り、お客さんの要望もあって下記のようなリスト値の変更が発生しました
(変更前の値は残っているが、対応する数値が変わった)

変更前

1:B
2:D
3:H


変更後

1:A
2:B
3:C
4:D
5:E
6:F
7:G
8:H


該当のカラムを 1:B → 2:B、2:D → 4:D、3:H → 8:H にそれぞれ変更したいが、
順番にUPDATE文を実行すると元が1 or 2だったデータが全て4になってしまう
3→8、2→4、1→2の順に1つづつUPDATE文を実行でも良いですが、CASE文を使用すれば複数のUPDATEを一括で実行出来ます。

UPDATE `table`
SET `column` = CASE WHEN `coumn` = ‘1’ THEN ‘2’ WHEN `column` = ‘2’ THEN ‘4’ WHEN `column` = ‘3’ THEN ‘8’ ELSE NULL END;

例は限定的ではありますが、WEHN ~の条件に応じて更新が出来るので一括更新が必要な場面では使い所がありそうです。

UPDATE/INSER文

既に存在しているレコードに対して一括で任意の項目を更新したい場合、
INSERT文の後ろにON DUPLICATE KEY UPDATE を付けることでPRIMARY KEYの項目がDBに存在していなければ新規行のINSERT、存在していれば指定の項目のUPDATEを行う

INSERT INTO `table`(`id` , `column1` , `column2`)
VALUES
('1' , 'aaa' , 'あああ'),
('2' , 'bbb' , 'いいい'),
('3' , 'ccc' , 'ううう')
ON DUPLICATE KEY UPDATE
column1 = VALUES(`column1`);

id がPRIMARY KEYであり
id = 1と2が存在するレコードで3は存在しないレコードである場合、
id = 1と2の行はcolumn1のみUPDATEされ、
3はcolumn2も含めて全ての項目がINSERTされます。

対象データ全件をCSVなどで出力しExcelなどでデータを更新し、
INSERT文を生成すれば更新したい項目のみをUPDATE出来ます。

おわりに

普段プログラムを書かない人間なので、システムの内部で具体的にどういった事をしているのかまでそこまで詳しく把握しておらず、これらをテスト時に都度調べながら使っていた頃は「こんな事が出来るのか」程度の認識でした。
DBを扱う処理は実際には今回挙げたようなクエリを実行して検索や更新が行われているので出来て当たり前といえば当たり前でしたね。



「業務のアイカタであり続けたい」
中小企業様向けERPソリューション

ai-cata.com

この10年で最も面白いAI技術【GAN】について

こんにちは大澤です.

今回は機械学習の研究分野でとても盛り上がっている「GAN」というAI技術をご紹介したいと思います.(ちょっと今更感ありますが…)

GANとは

2014年にイアン・J・グッドフェロー(Ian J. Goodfellow)らによって発表された,機械学習の新しいアルゴリズムです.

ちゃんとした名前は「Generative Adversarial Networks(敵対的生成ネットワーク)」と言います.

これの頭文字を取って「GAN」ということなのですね.

敵対的"生成"ネットワークというだけあって,何かを生成することができる技術です.

2014年発表から現在に至るまで,毎日のようにGANに関する新しい研究論文が発表されており,AI研究の分野ではとても盛り上がっています.

そしてこのGANはヤン・ルカンというAI研究者からこのように評されています.

"This, and the variations that are now being proposed is the most interesting idea in the last 10 years in ML, in my opinion."

機械学習において,この10年で最も興味深いアイディアだと思う

このGANは何がそんなに面白いのでしょうか.

GANでできること

GANのアルゴリズムなどの難しい説明はさておき,とりあえずどんなことができるのかをご紹介します.

まずはこちらの画像を見てみましょう.

f:id:kyoshi0000:20201002151344p:plain

カバンの線画ですね.

このカバンに色を付けてリアルなカバンを描きあげたいと思います.例えばこんなものはどうでしょうか.

f:id:kyoshi0000:20201002151136p:plain

すてきなカバンですね.使い込まれた革製品のような風合いを見事に表現していますが…実はこれ,GANによって着色がされています.

f:id:kyoshi0000:20201002152327p:plain
引用[Image-to-Image Translation with Conditional Adversarial Networks]

つまりINPUTとして線画を与えると,それに対応したカラー画像を自動で生成してくれるわけです.

これはpix2pixと呼ばれており,これ以外にも様々なことができます.論文の中でいろいろな生成パターンを見せてくれています.論文の中身は英語なのですが,画像がたくさんあるのでそれを見るだけでも割と楽しいです.

また,上記のように2つの対応した画像から学習するタイプではなく,「教師なし」つまり人が正解データを直接与えずとも2つのドメインの特徴を入れ替えることができるcycleGANというものもあります.

f:id:kyoshi0000:20201007095444p:plain
引用[Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks]

こちらのすごいところは「とりあえずシマウマの写真をたくさん集めてくる」「とりあえず馬の写真をたくさん集めてくる」それだけで上記の入れ替えが可能となるところです.

なんとなく「GANってすごいな」というのが伝われば幸いです.ちなみにpix2pixに関しては,こちらのサイトで簡単に試すことができます.

Image-to-Image Demo

線画から「猫」を生成できるとのことだったので,こんなクリーチャーを生み出して遊んでました.

f:id:kyoshi0000:20201002155445p:plain

毛ガニです.ちゃんと目の部分も認識してるところがホラーですね.

ともあれ,数年前までは「単純作業はAIに任せ,人は創造的な作業を担当するべきだ」などと言われていましたが,このGANというアルゴリズムが誕生したことで,AIでも創造的な作業が可能になったわけです.

GANの仕組み(簡単ver.)

GANの面白いところは上記のように絵が書けるだけではありません.学習方法もちょっと変わっています.

以前瓜生さんが少しGANに触れた記事を書いていましたが,GANの学習方法は「絵画の贋作作家と鑑定士」に例えられることが多いです.

贋作作家が本物を真似た絵を複数描き,本物に混ぜて鑑定士に渡す

 ↓

鑑定士は複数の絵の中から贋作と本物を見極める

 ↓

その結果を元に贋作作家はより本物に近い贋作を複数作り上げ,本物に混ぜて鑑定士に渡す

 ↓

鑑定士はより見分けづらくなった中から贋作と本物を見分ける

 ↓

以下ループ

これがGANの簡単な仕組みです.つまりGANでは「生成モデル(贋作作家)」と「分類モデル(鑑定士)」の異なる2つのモデルを交互に,しかも競い合うように学習させているわけです.これが”敵対的”と言われる所以なのですね.

ただ,この学習はとても繊細なパラメータチューニングが必要になってきます.なぜなら「贋作作家と鑑定士のどちらか一方がとても優秀(劣っている)」という状況を作ってはいけないからです.

例えば鑑定士が節穴で贋作作家の作った偽物をなかなか見抜けない場合,駄作であった場合でも本物と判定してしまうので,贋作作家の技術は向上せずに駄作ばかりを生み出します.

逆に鑑定士が優秀すぎる場合,贋作作家がどんな作品を作っても偽物と見破られてしまうため,贋作作家としてはどのように改善すれば本物に近くなるのかがわからないままになってしまいます.

つまり2つのモデルのパワーバランスが大切になってくるということなのです.

GANの活用

さて,これまでは「絵描き」としてのGANを紹介してきました.それだけでも十分なインパクトでしたが,GANの技術を「面白かった」だけで終わらせてしまうのはもったいないので,どんな活用方法があるのか?という点を最後にすこしご紹介します.

SRGAN(超解像化)

例えば96✕96pxの画像から4倍の384✕384pxに変換することを想定します.

通常であればBicubic補間あるいはBilinear補間を利用して画像を大きくしますが,これでは画像がボケてしまいます.しかしその補間したい部分をSRGANで生成してあげると,ボケない拡大画像(超解像)を実現することができるのです.(論文)

f:id:kyoshi0000:20201009145028p:plain
引用[Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network]

AnoGAN

こちらはGANを異常検知に応用したものです.正常データのみ学習させ,与えた画像から正常な画像を生成するようなモデルを作ります.すると,異常な画像(下図1段目)を与えたときも,そこから正常な画像(下図2段目)を作り出そうとします.

その差分をとってあげることで異常箇所を浮かび上がらせることができるのです.

f:id:kyoshi0000:20201009151913p:plain
引用[Unsupervised Anomaly Detection with Generative Adversarial Networks to Guide Marker Discovery]

さいごに

いかがでしょうか.GANの面白さや可能性が伝われば幸いです.アイディア次第で面白いことが色々とできそうですので,これからの動向にも注目していきたい技術です.

また,弊社ではAI導入セミナー(オンライン)も実施予定です.

"AIを導入したいけど,何から手を付けたらいいかわからない"

"AIをビジネスに活用したいけど,何に利用できるのかわからない"

"そもそもAIがどんなものかわかっていない"

といった方々を対象にしており,AIをどのように活用し,どのように導入するかという内容になる予定です.

ご興味のある方は弊社までお問い合わせいただけますと幸いです.

DockerでnginxとAPIを動かす

どうも、こんにちは。としと申します。
いかがお過ごしでしょうか。

真夏のピークが去りましたね。
若者の全てが染みるこの頃です。(下書き期間が長すぎて、ちょっと今じゃない感は無視してください(´Д`;))

さて、今までElastic Beanstalk の記事を数本書かせていただきました。
その後、ローカルでDockerを動かすことが出てきたので、Dockerの設定と、どうせローカルで使うならまずはElasticBeanstalk on Docker を使ってみようじゃないか! と思い、色々調べながらやってみております。

(以下、Docker Desktop がインストールされている前提です。)
まずはDockerfile...

# ベースイメージを指定
FROM node:latest

# 作業ディレクトリ作成して設定します
WORKDIR /usr/share/nginx/html/

# 必要な環境変数をここに記載します
ENV JWT_SECRET=""
ENV JWT_EXPIRATION=""
ENV MYSQL_DATABASE=""
ENV MYSQL_READ_HOST=""
ENV MYSQL_READ_PASSWORD=""
ENV MYSQL_READ_PORT=""
ENV MYSQL_READ_USERNAME=""

# package.jsonをこぴります
COPY package*.json ./

RUN npm i

# アプリケーションのソースをバンドルします
COPY . .

# PORT
EXPOSE 8081

CMD ["node", "dst/server.js"]

とりあえずこれで

docker build -t userName/api .

↑build

docker run --name api -p 8081:8081 -d userName/api

↑これで起動

で動いてくれました。

docker ps

↑これで動いている一覧がみれます。

docker ps -a

↑ -a をつけると停止しているものもみえます。

docker stop api

↑一回止めましょう。

続いて docker-compose を使っていきます。 先ほどのDockerfileはアプリケーションのDockerfileなので、ファイル名をDockerfile-appに変更します。

新しくDockerfile-web を作ります。

# ベースイメージを指定
FROM nginx:latest

# default.conf 書き換え
COPY ./default.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

default.conf

server {
    listen       80;
    server_name  localhost;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://api:8081/;
    }
}

続いて docker-compose.yml を作ります。

version: '3'
services:
  web:
    build:
      context: docker      # Dockerfile保存場所
      dockerfile: Dockerfile-web    # Dockerfileファイル名
    image: nginx      # docker image name
    container_name: nginx       # docker container name
    expose:
      - 80
    ports:
      - 80:80

  app:
    build:
      context: ./      # Dockerfile保存場所
      dockerfile: Dockerfile-app   # Dockerfileファイル名
    image: api                  # イメージ名
    container_name: api         # コンテナ名
    expose:
      - 8081
    ports:                          # ポート接続
      - 8081:8081
    volumes:                        # mount workdir
      - .:/usr/share/nginx/html/
    command: ["node", "dst/server.js"]

今回のフォルダ構成
PJ/Dockerfile-app
PJ/docker-compose.yml
PJ/docker/Dockerfile-web
PJ/docker/default.conf

その後

docker-compose up --build

↑を実行すると動いてくれます。

f:id:Toshi_bw:20200630122310p:plain

このような感じになれば成功です!

調べながらなので、中々時間がかかりました...

次回はAWS ECR にDocker imageをあげてみるとこら編を記載しようかなと思います。



「業務のアイカタであり続けたい」
中小企業様向けERPソリューション

ai-cata.com

Airtableを試していたらGoogleからTablesも発表された

kintoneの類似サービスのAirtableを少し試してみました。

Airtableとは

Airtableの特徴

  • 画面の操作感がExcelやSpreadSheetに近い
    • kintoneだと画面遷移が必要で静的なページが多いです。

f:id:usami-t:20201002141631g:plain
Airtable操作イメージ

  • ルックアップが即時反映

    • kintoneだとデフォルトの動作はルックアップの項目を更新しても、参照しているデータは更新されません。実現するにはプラグインなど必要です。
    • Airtableはデータベースで外部キー参照している感覚です。
    • また、1つのフィールドに複数の値を持つことが可能です。

      https://support.airtable.com/hc/article_attachments/360024030014/linked_records_2.gif

  • 日本語の情報が少ない

    • 日本語での情報量はkintoneの圧勝です。
  • 無料プランがある Pricing - Airtable

    • kintoneは基本的に有料です。
  • FormのURL共有

    • レコードを追加可能なフォームのURLが即時共有できます。
    • プランによってはパスワード制限も可能です。
  • 1つのアプリ内に複数テーブル保持

    • kintoneでは1テーブルごとにアプリと呼びます。Airtableはbaseと呼ばれるアプリの概念があり、その配下に複数テーブル持つことが可能です。
  • Airtableとkintoneの共通点

以下の機能はどちらのサービスでも対応してます。

Tables

Airtableを試しているうちにGoogleがベータ版を公開しました。(現在使用可能なのはアメリカのみ)

blog.google

Googleの紹介動画を観ると、Airtableと似た操作感なのではないかなと思います。

  • データサマリの通知機能が強そうです。

所感

弊社ではユーザ向けWeb画面と管理画面の両方を開発する案件が多いのですが、 下記のような案件があってもいいなと感じました。

  • バックエンドはkintoneまたはAirtableで構築し、管理画面扱いとする。
  • フロント画面はAPIでアクセスを行う。
  • その他SaaSなどの外部サービスとのデータ連携を行う。
  • 基本機能で出来ない部分だけ弊社で開発 など...

kintoneやAirtableにREST APIが用意されているというのは結構強みなのかなと思います。

サービス内の標準機能でどこまで出来るのかといった点がシステム発注側の方も詳しいと、 実装難易度、工数、費用など認識が共有しやすくなるんじゃないかなと感じます。

SaaS導入などお考えでしたら是非弊社へお問い合わせください!

CSVファイルからExcel開いて困った世にも奇妙な話

どうもおはこんばんにちは。
まだまだ駆け出し中の社員kobaです。
もう気付けば9月も終わってしまいますね・・・
年々時の流れの速さに困惑してしまいます ´д` ;

前回は7月にExcelファイルからPDFファイルの変換で右往左往した話を
ご紹介させていただきました。

tech.briswell.com

今回は第2弾ということで
CSVファイルからExcelファイルを開いたら困った世にも奇妙な話を
ご紹介したいと思います(※ご存知の方がいらっしゃったらすみません)

当社では数々のシステムを扱ってますので
システムデータをCSVファイルに落として
CSVファイルからExcelを開いて
CSV内容とシステムデータが一致しているか確認する作業を行っております。
今回はその作業で起こった現象が2つあるので備忘録の意味でも
書かせていただきたいと思います。
ちなみに私が使っているPCはMacです。

CSVからExcelに変換したファイルデータ文字化けした

CSVファイルからExcelファイルへ変換したらファイルデータの一部が文字化けしました

f:id:briswellyuki:20200926163939j:plain
変換したExcelファイル文字化けした例
当初なにかやらかしてしまったかと思いましたが、
調べてみると文字コードが対応していないのが原因でした。
文字コードは簡単に言ってしまうと、
文字の種類に番号を割り振ったもののことをいうみたいです。
コンピューターはテキストの文字をその番号で判断しており、
対応されていない番号のファイルは正しく変換されず、
上の写真のような文字化けの状態になってしまいます。

・文字化けになったときの解決方法

CSVファイルをテキストエディットで開いて複製→保存すると
下記写真のような画面になります。

f:id:briswellyuki:20200926162808j:plain
CSVファイルをテキストエディットで開いて複製→保存時の画面

標準テキストのエンコーディングの部分が文字コード変換の設定になります。
どうやら元のCSVファイルはUTF-8になっていたようです。

f:id:briswellyuki:20200926162811j:plain こちらをShift-JISにして保存すれば
f:id:briswellyuki:20200926164244j:plain 正しく変換できました〜
かなり初歩的ではありますが、
文字コードの変換を忘れてCSVExcelに変換することは多い気がします。

1つのセルに複数の数値があるCSVを変換したら

1つのセルに複数の数値がある項目のCSVExcelに変換した場合、
Excelが勝手に1つの数値に変換してしまうことがありました。

f:id:briswellyuki:20200926171251j:plain
1つの数値に変換されてしまう例

別プロジェクトで複数の数値がある項目のCSVは正しく変換されている・・・
比べてみると最初以降の数値の前に半角スペースが入っているみたいでした。

f:id:briswellyuki:20200926174239j:plain
テキストエディターツールmiで開いた通常のCSV
半角スペース入れて変換してみたら
f:id:briswellyuki:20200926174010j:plain
テキストエディターツールmiで開いた半角スペース入力したCSV
f:id:briswellyuki:20200926174017j:plain
半角スペース入れたCSVを変換したExcel
正しく複数の値が1つのセルに表示されるようになりました〜
内容が薄いですが、なにか少しでも上記の情報がお役に立てたら幸いです。



「業務のアイカタであり続けたい」
中小企業様向けERPソリューション

ai-cata.com

江戸屋敷がすぐそばに

f:id:KenjiU:20200927203521j:plain
Kazutripさんによる写真ACからの写真

夜な夜な江戸の古地図を眺めてタイムスリップを楽しんでおります。

現代の地図と見比べながら、当時あったが今はないもの、今もまだあるものと、違いを見つけながら歴史を紐解いていくと、とても楽しいです。

さて、弊社株式会社ブリスウェルですが、2019年2月に「渋谷区広尾1丁目」→「港区芝大門1丁目」に移転しました。

https://www.edomap.jp/
こちらのいつもお世話になっております「大江戸今昔めぐり」アプリで、それぞれの場所の地図を眺めてみましょう。

f:id:KenjiU:20200927203958p:plain
移転前:渋谷区広尾1丁目

f:id:KenjiU:20200927204031p:plain
移転後:港区芝大門1丁目

なんと
移転前の広尾(恵比寿)オフィスは、赤穂藩森家の下屋敷が目の前にあり、
移転後の大門オフィスは、赤穂藩森家の上屋敷が目の前にありました。
オフィスの窓から見ていた外の風景に、お屋敷があったことと、それも同じ藩主家の屋敷だったことには驚きです。両方の場所は、現在、平地で区画もきれいに四方に仕切られており、当時大きな建物があったような雰囲気はあります。

ちなみに
大門の地図の①には「赤穂藩森家上屋敷跡出土の石垣石」の遺跡があります。

f:id:KenjiU:20200927204605j:plain
赤穂藩森家上屋敷跡出土の石垣石

大門の地図の②には「芝神明町町屋敷跡」の遺跡があります。

f:id:KenjiU:20200927204654j:plain
神明町町屋敷跡

江戸時代の暮らしの息吹を感じますね!

と、ここで江戸ブログではなくテックブログなので一つAI技術をご紹介いたします。

弊社の大門オフィスから徒歩18分ほどの場所にある愛宕山。江戸市中において最も高い山(標高26メートル)で、江戸湾まで一望できた観光名所でした。以下の写真はその愛宕山から撮影した江戸の町です。

f:id:KenjiU:20200927204915j:plain
引用:愛宕山から見た江戸の町 : 江戸時代(幕末) | https://pin.it/5yfx90Z

この白黒写真をディープラーニングを使って色付けしてみます。

f:id:KenjiU:20200927205032j:plain
愛宕山から見た江戸の町

江戸時代がぐっと身近に感じられますね!
弊社オフィスの前にもこのような屋敷が連なっていたのでしょう。
では、拙者はこれにて失礼致す、御免。

About the AWS Auto Scaling

Hello, everyone.

It's Shun.

 

今回は「AWS Auto Scaling(オートスケーリング)」についての概念をまとめてみました。

「こういったことができるだ、へー、便利だね」くらいに感じていただけると、幸いです。

 

Auto Scalingのユースケース

全体的に見ると必要なリソース量は少ないが、瞬間的にリソースが必要になる場合があり、一番リソース量が増える時のリソース量にサーバーのスペックを合わせているオンプレミス環境構成で運用をしている場合。

 こういったケースに、Auto Scalingを使用すると、コストを最適化することができます。

以下、Auto Scalingあり/なしの場合のイメージを図で示してみました

Auto Scalingあり/なし比較

Auto Scalingなし

f:id:artistyuiguitarelegance:20200923165940p:plain

オートスケーリングなし

実際には使用していない部分(上図ピンク塗り箇所)が使用料の2倍以上あるため、必要なリソース量に対してマシンのスペックが見合っていない。

Shun「なんで、実際にはサーバーを使っていない時間帯が多いのに、こんなに使用料を払わなきゃいけないんだよ・・・はぁ、萎える。」みたいな状態です。

コスト最適化の面で改善の余地がかなりあります。

Auto Scalingあり 

f:id:artistyuiguitarelegance:20200923170033p:plain

オートスケーリングあり

実際には使用していない部分がないため、必要なリソース量に対してマシンのスペックが見合っている。

Shun「今月はこんだけサーバーを動かしたんだ。それにしてもリソースの使用料は変わらないのに、Auto Scalingしていない頃と比べてこんなに費用を削減できるんだね、すごい・・・じゃあ、浮いたお金で美味しいもの食べにでも行きますかね^-^」みたいな状態です。

コスト最適化がされています。

 

Auto Scalingのトリーガー

 Auto Scalingありの図中の吹き出しでご説明いたしました、この部分ですが、

必要なリソース量が増えれば、そのリソース量に応じてマシンの性能を拡張し、必要なリソース量が減ると、そのリソース量に応じてマシンの性能を縮小する

どういった条件の場合((例)CPU使用率が80%を超えたら)にマシンの性能を拡張し、どういった条件の場合((例)CPU使用率が70%を割ったら)にマシンの性能を縮小するといったようなことを設定できます。

 →Amazon Cloud Watchと組み合わせて使用します(Cloud Watchはざっくりご説明すると、マシンの使用量などを図で視覚的に見ることができるものとでも覚えておけば、まずはよろしいのではないかと思います)

 

条件の設定値はマネージメントコンソール上からいつでも簡単に変更することができますので、運用していく中でマシンの設定値をチューニングしていくのがいいと思います。

 

最後に

以上、「Amazon Auto Scaling」の概念をかいつまんでご説明させていただきました。

コスト最適化については、環境構成を変更したり、マシンのスペックを下げたりとその他にも色々考えられることはあると思いますが、今回ご紹介させていただきました「Amazon Auto Scaling」は特に、コスト最適化の面で貴人の大きな助け舟になると思います。

必要な分だけ使って、使った分だけ使用料を払いたいですね。

 

それでは、今回はこの辺で。

Thank you so much, see you next time✋

 

 

ローカルPC上の開発中のネットワークサービスを外部公開できるサービスngrok

はじめまして、私はPhiと申します。
システム開発業務に携わってます。

最近は外部サービスと連携するためwebhookを開発しています。
webhookなので、オンラインURLがないとテストできないです。
毎回テストするため、elasticsbeanstalkへデプロイするのは結構面倒 + 時間かかります。
上記の解決策を探していたら、ngrokを見つけました。

NGROKとは?

ngrokとは「セキュアトンネル経由、NATおよびファイアウォールの背後にあるローカルサーバーをパブリックインターネットに公開」というサービス。 f:id:phint:20200831225715p:plain

利点は?

  1. webhook/chat bot 開発する時にとても便利
  2. モバイルアプリもしくはSPAのバックエンドサーバをdebugできる
  3. リモートでお客さんにウェブサイトのデモを紹介できる
  4. ローカルサーバを別の環境(スマホwindows/linux/macos)でテストできる

使い方

ngrokでアカウントを登録して、アプリをダウンロードしたら使えます。

  1. アカウント登録:
    このサービスは無料で使えますが、有料プランもあります。開発のみの場合は無料を使っても全然問題ないと思います。
    ここで登録してください。
    登録さた後、ダッシュボードへ遷移されます。
    ここで認証ためのコマンドを見えます。
    例: ./ngrok authtoken xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    アプリダウンロードした後、例のコマンド叩いたら、ログインできます。

  2. アプリダウンロード:
    ダウンロードリンクです。
    私はmacOS使っていますが、windowsも大体同じです。
    ※下記画像はmacの画像になります

まずはダウンロードファイルを解凍します。そのあとは terminal を起動して、解凍先のフォルダーへ移ります。(私はApplications フォルダーに解凍しましたから、Applicationsへ移ります)
f:id:phint:20200901123155p:plain ここで、上記の認証コマンドを実施します。 f:id:phint:20200901123711p:plain ここまでは準備のステップは終わりました。ngrok使いしょう!
./ngrok http <port> この簡単なコマンドでローカルサーバがパブリックインターネットに公開されます。私のローカルサーバは port 3333 で動いてますから、 ./ngrok http 3333 実施します。これは結果です。 f:id:phint:20200901125700p:plain httpsのリンクもあります、便利ですね。無料プランですから、毎回コマンド実施したらランダムURL返却されます。
ngrokのダッシュボードページでURLも見えます。 f:id:phint:20200901130104p:plain そして、コマンド実施結果の Web Interface http:127.0.0.1:4040 をアクセスすればリクエスト詳細を検査できます。 f:id:phint:20200901130359p:plain

他の機能も色々ありますが、今回の記事はここまでになります。皆様ngrokを試して楽しんでみてください!

PHPのメモリについて(Part2)

どうもこんにちは。BriswellのTuanと申します。
今日また、PHPのメモリについて続きたいと思います。
前回の内容を参考したい方は下記のリンクを参考してください。

PHPのメモリについて(Part1) - Briswell Tech Blog

PHPは自動的にメモリ管理できると言うことを分かりましたが、何を管理しているのでしょうか?

まず、値代入参照代入を簡単に説明します。
PHPには基本的にオブジェクト以外各変数は値代入です。
例えば下記のコード確認しましょう:

<?php 
$a = 1; 
$b = $a;    
$a++;    
var_dump($a, $b);  
    
$x = (object)['value' => 3]; 
$y = $x;    
$x->value = 10;  
var_dump($x); 
var_dump($y);

実行結果

int(2)

int(1)

object(stdClass)#1 (1) { ["value"]=> int(10) }

object(stdClass)#1 (1) { ["value"]=> int(10) }

$a, $bの値は簡単にわかるでしょうか!
しかし、$x$yはどう思ういますか? $x, $yはオブジェクトですから値代入ではなく、参照代入ので、
個別のオブジェクトですが、実際は同じメモリ位置に参照しますので、$xを更新すると、$yにも反映されます。

関数の引数もデフォルトは値渡しです。

<?php 
function fnByVal($v) { 
        $v = "test";  
}   

// 参照渡しを指定
function fnByRef(&$v) 
{   
        $v = "test";  
}   
$y = 'Briswell';    
fnByVal($y); var_dump($y); 
fnByRef($y); var_dump($y); 

実行結果

string(8) "Briswell"
string(4) "test"

上記のコードを実行して、fnByValを呼んだ後に$yの値はそのまま「Briswell」でしょうか! でもfnByRefの場合、$yの値更新されました。

ちょっと面白いと思いますが、下記のコードを実行したら、結果は想定と同じでしょうか!自分で試して、是非コメントで説明してください。

<?php 
function fnByVal_($obj) {  
        $obj->value = "test";  
}   
$x = (object)['value' => 1]; 
fnByVal_($x); var_dump($x);    

PHPは必要であれば、自動的にメモリをアロケート又は解放します。
ただし、「必要であれば」はいつでしょうか? これから、色々を試しながら確認しましょう。

※注意:以降の例は基本的に検証の想定通りですが、PHPバーションによって、メモリ管理方違う部分があるので結果違います。ご注意してください。

例1:

<?php 
    $mem = memory_get_usage();    
    $a = str_repeat("1", 1000); // ①       
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    $b = $a;                    // ②
    $c = $b;                    // ③ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
        
    $a = $a . '1';               // ④ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
        
    unset($b);                   // ⑤ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    unset($c);                   // ⑥ 
        
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 

実行結果

used mem: 1280
used mem: 1312
used mem: 2592
used mem: 2592
used mem: 1312

ソース見るだけ分かりずらいと思いますが、下図を見てください。

f:id:tuanda:20200831183105p:plain

f:id:tuanda:20200831183143p:plain

配列も同じ管理方です。
例2:

<?php 
$mem = memory_get_usage();    
$a = array_fill(0, 1000, '1'); 
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$b = $a;    
$c = $b;    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[0] = '2';   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[] = '1'; 
echo count($a)."\n";  
echo count($b)."\n";  
echo count($c)."\n";  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    
>unset($b);   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
unset($c);   
    
>echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";   

実行結果

used mem: 36920
used mem: 36952
used mem: 73872
1001
1000
1000
used mem: 73872
used mem: 73872
used mem: 36952

例3:

<?php 
$mem = memory_get_usage();    
$a = array_fill(0, 1000, (object) array('x' => '1'));  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$b = $a;    
$c = $b;    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[0]->x = '2';    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[] = '1'; 
echo count($a)."\n";  
echo count($b)."\n";  
echo count($c)."\n";  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    
>unset($b);   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
unset($c);   
    
>echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";   

実行結果

used mem: 36960
used mem: 36992
used mem: 74288
1001
1000
1000
used mem: 74288
used mem: 74288
used mem: 37368

試した結果上で、PHPには同じメモリエリアに複数変数が参照できますが、
それぞれの変数がいずれか更新したい場合は別のメモリエリアをアロケートします。
これは大切だと思います。

*データベースから数万件のデータ抽出する時に、注意しないと、「Fatal error: Out of memory」発生可能性が高いです。

例えばデータ処理はほとんどForeachというループ命令を使ってますが、下記の2つバーションのForeach確認しましょう。

一般的バーション

<?php     
$mem = memory_get_usage();        
$a = [  array_fill(0, 1000, '1'),      
        array_fill(0, 1000, '2'),     
        array_fill(0, 1000, '3'),     
        array_fill(0, 1000, '4')];        
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";     
foreach ( $a as $key => $item) {        
     $a[$key][0] = '9';       
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";     
}       

実行結果

used mem: 148056
used mem: 185384
used mem: 222304
used mem: 259224
used mem: 296144

参照バーション

<?php 
$mem = memory_get_usage();    
$a = [  array_fill(0, 1000, '1'),  
        array_fill(0, 1000, '2'), 
        array_fill(0, 1000, '3'), 
        array_fill(0, 1000, '4')];    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
foreach ( $a as <b><span style="color: #0000cc">&</span></b>$item) { 
    $item[0] = '9';        
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
}   

実行結果

used mem: 148056
used mem: 148152
used mem: 148184
used mem: 148216
used mem: 148248

結果見ると、どちら効率かすぐ分かりますね。でも、一般的皆あまり参照のバーション使ってないと思います。

PHPは自動的にメモリを解放できますが、必要であれば、自分達「unset」で解放できます。
PHPソースには配列を多分一番よく使うデータ型ですが、参照代入ではなくて、値代入ので、ご注意してください。
意外の増やすメモリのケースが多いと思います。

ではPHPのメモリについてここまで終わります。
みなさん是非試して確認して、実際のプロジェクトに適用すれば、良かっただと思います。

動画の人物をホネホネ化

今回のAIブログは、骨格検出(通称:ホネホネ化)についてご紹介いたします。
骨格検出とは、動画または写真の中から人物の骨格を検出する技術となります。
サクッとどのようなものなのか、見ていきましょう。

【下北ラヴァーズ】スマートスピーカー

こちらの弊社Uri&Yuki漫才コンビ「下北ラヴァーズ」のダンス動画について骨格検出をしてみます。

微妙にシンクロしていないですね...(いや微妙というか全然かも!?)
骨格検出を利用すれば、実際にどのくらいシンクロしていないかを数値で定量的に評価することもできます。

骨格検出には「tf-pose-estimation」というモデルを使用します。
これは以下の「OpenPose」という骨格検出アルゴリズムを「TensorFlow」用に移植したものとなります。

github.com

では、早速ですが検出結果を見ていきましょう!

youtu.be

ほぼ完璧にホネホネ化できていますね。素晴らしいです。
骨格の位置を可視化するだけでなく、骨格の各ポイントについてXY座標で出力することもできます。

例えば、右腕の座標位置の推移を見てみると

f:id:KenjiU:20200901185451p:plain
Uri(立ち位置左)の右腕の座標位置推移

f:id:KenjiU:20200901215246p:plain
Yuki(立ち位置右)の右腕の座標位置推移

f:id:KenjiU:20200901185550p:plain
UriYukiの差分

X座標の差分が徐々に大きくなってきてますね...
このように「微妙にシンクロしていない」というのを数値で評価することができるようになります。面白いですね!

次は具体的にシンクロ度「何%」と出せる仕組みも作っていきたいなと思っております。

Briswell AI Team