2018年8月17日金曜日

サイボウズLiveのデータをサイボウズ Officeに取り込んでみた!

社内の連絡ツールとして長らく「サイボウズLive」を使用してきましたが、残念ながら来年4月にサービスが終了してしまいます。
いろいろ検討した結果、「サイボウズ Office」を利用することになりました。

乗り換えセミナーで、サイボウズLiveのデータを完全には移行できないことが分かりましたし、また、よくよく考えると過去のデータの必要性も高くありません。ただ、そんな中でも、メンバー名簿とマイカレンダーだけは再利用したいので、移行にチャレンジしてみました。


メンバー名簿


グループのメンバーデータを「cybozu.com用CSV」としてエクスポートします。
このファイルをそのままcybozu.comでインポートすると、エラーになります。
というのも、必須項目である「新ログイン名」と「パスワード」が、インポートしたデータでは空だからです。
一件ずつ手で編集するのは面倒なので、変換プログラムを作成しました。

import sys
import csv
import random
import string

contents = []

r_filename = sys.argv[1]
with open(r_filename, 'r') as f:
    r = csv.reader(f, delimiter=',')
    for i, row in enumerate(r):
       if i > 0:
           # 新ログイン名
           row[2] = row[0]
           # パスワード
           row[3] = ''.join(random.choices(string.ascii_letters + string.digits, k=8))
       contents.append(row)

w_filename = sys.argv[2]
with open(w_filename, 'w', newline='') as f:
    w = csv.writer(f, delimiter=',', quoting=csv.QUOTE_ALL)
    w.writerows(contents)


これでエラーなくユーザー情報を取り込むことができました。


マイカレンダー


マイカレンダーの「csvで出力する」からデータをエクスポートします。
出力したCSVファイルを読み込み、スケジュールの項目との関連付けを行います。
この時、サイボウズLiveの「タイトル」は「予定」ではなく「予定詳細」に関連付けた方がいいでしょう。


というのも、「予定」は「会議」「外出」といったリスト項目であり、「予定詳細」の方に訪問先など具体的な内容を表示させたいからです。(「予定」に関連付けてもエラーになるわけではなく、タイトルの内容がリスト項目に追加されます。)


















サイボウズ Officeのスケジュールをしばらく使用してみて、サイボウズLiveに比べて不満な点が二つあります。

一つは、非公開予定の表示方法です。
サイボウズLiveは公開予定の方にアイコンが付いてスマートに表示されていたのですが、サイボウズ Officeでは非公開予定が「XXXXX(非公開)」と表示されます。私はプライベートの予定も登録しているので、非常に見づらくなってしまいます。

もう一つは、公開予定の公開範囲です。
サイボウズLiveではメモまでは公開されません。例えば、出張予定では搭乗便の時刻、座席番号だけでなく予約番号を、訪問予定では打ち合わせした内容などを、メモに登録していました。そうした情報までは他人に公開したくないので、その点は予定詳細までしか公開しないサイボウズLiveの方が良かったなあと思います。

またいつか、どこかで。

2018年8月9日木曜日

ディープラーニングを体感しよう:第6章(プログラムコードを見ていこう2)



こんにちは。よっしーです。

これまでの記事:
ディープラーニングを体感しよう:第1章(まずは環境構築)
ディープラーニングを体感しよう:第2章(Python環境を構築する)
ディープラーニングを体感しよう:第3章(プログラムを動かしてみよう)
前回は、プログラムコードの内容を見ていきました。

・ライブラリのインポート処理
・手書き数字のデータセット取得
・学習用データ、テスト用データの整形

について解説しましたので、

今回も、前回に引き続き、プログラムコードを見ていきたいと思います。


model = Sequential()
model.add(Dense(256, input_dim=784))
model.add(Activation("sigmoid"))
model.add(Dense(128))
model.add(Activation("sigmoid"))
model.add(Dropout(rate=0.5))
model.add(Dense(10))
model.add(Activation("softmax"))


ここの処理で、ニューラルネットワークを作成しています。
正直、このコードだけ見ても、なかなかイメージが沸きません。

1行目の Sequential() は、
Sequentialモデルというニューラルネットワークの層を積み重ねたモデルを使用することを表しています。

その後の add() で、ニューラルネットワーク層を構築しています。
ここでは3層の作られており、

784(入力層) → 256(隠れ層) → 128(隠れ層) → 10(出力層)

という形でが形成されます。(※入力層はカウントされないため3層となります。)
で、この数値はノードを表しています。

文字だけで書くと「チンプンカンプン」なので絵にしてみましょう。


イメージとしてはこのような構成となります。
実際に入力と出力を紐付けると、以下のような形となります。



層を進むにつれて、ノード間で情報を渡し、出力内容を導き出すといった形となります。
ここでは、「シグモイド」と「ソフトマックス」いう活性化関数を利用して、パターン検出しています。

これらの活性化関数については、数学の難しい公式を利用して結果を得ています。
正直、数学好きでないと内容についていけないレベルです。

なので、私は深追いせず、そういった名前のロジックを使っているんだな。
という程度で理解しています。


今日はこのあたりで。ではまた~。

2018年8月2日木曜日

ディープラーニングを体感しよう:第5章(プログラムコードを見ていこう1)



こんにちは。よっしーです。

これまでの記事:
ディープラーニングを体感しよう:第1章(まずは環境構築)
ディープラーニングを体感しよう:第2章(Python環境を構築する)
ディープラーニングを体感しよう:第3章(プログラムを動かしてみよう)

前回は、ディープラーニングについて説明しました。

今回は、実際にプログラムコードの内容について見ていきたいと思います。

以下が実行したプログラムになります。

import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
from keras.layers import Activation, Dense, Dropout
from keras.models import Sequential, load_model
from keras import optimizers
from keras.utils.np_utils import to_categorical

(X_train, y_train), (X_test, y_test) = mnist.load_data()

X_train = X_train.reshape(X_train.shape[0], 784)[:6000]
X_test = X_test.reshape(X_test.shape[0], 784)[:1000]
y_train = to_categorical(y_train)[:6000]
y_test = to_categorical(y_test)[:1000]

model = Sequential()
model.add(Dense(256, input_dim=784))
model.add(Activation("sigmoid"))
model.add(Dense(128))
model.add(Activation("sigmoid"))
model.add(Dropout(rate=0.5))
model.add(Dense(10))
model.add(Activation("softmax"))

sgd = optimizers.SGD(lr=0.1)
model.compile(optimizer=sgd, loss="categorical_crossentropy", metrics=["accuracy"])

history = model.fit(X_train, y_train, batch_size=500, epochs=5, verbose=1, validation_data=(X_test, y_test))

plt.plot(history.history["acc"], label="acc", ls="-", marker="o")
plt.plot(history.history["val_acc"], label="val_acc", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()


これだけ見てもさっぱりわからないので、ちょっと解説していきたいと思います。


このプログラムでは以下3つのライブラリを使っています。

numpy : 数値計算を効率的に行うためのライブラリ。
matplotlib : 各種グラフを作成しデータの可視化が可能とするライブラリ
keras : ニュートラルネットワークを扱うためのライブラリ

これらを使うためのインポート処理が以下です。

import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
from keras.layers import Activation, Dense, Dropout
from keras.models import Sequential, load_model
from keras import optimizers
from keras.utils.np_utils import to_categorical

で、次の処理で手書き数字データセットを取得しています。

(X_train, y_train), (X_test, y_test) = mnist.load_data()

ネット上から手書き数字データセットのダウンロードを行い、X_train, y_train, X_test, y_test へ展開しています。

この1行だけ見てもまったくわからないので、どんなデータかを解説すると、

X_train:学習用の画像データ
X_test:テスト用の画像データ

画像データは、28x28 pixel の グレースケール生値です。
0 ~ 9 の手書き数字の画像となっています。

イメージしやすいように1データ抜き出してみました。

[[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   3  18  18  18 126 136 175  26 166 255 247 127   0   0   0   0]
 [  0   0   0   0   0   0   0   0  30  36  94 154 170 253 253 253 253 253 225 172 253 242 195  64   0   0   0   0]
 [  0   0   0   0   0   0   0  49 238 253 253 253 253 253 253 253 253 251  93  82  82  56  39   0   0   0   0   0]
 [  0   0   0   0   0   0   0  18 219 253 253 253 253 253 198 182 247 241   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  80 156 107 253 253 205  11   0  43 154   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0  14   1 154 253  90   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0 139 253 190   2   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0  11 190 253  70   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  35 241 225 160 108   1   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0  81 240 253 253 119  25   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  45 186 253 253 150  27   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  16  93 252 253 187   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 249 253 249  64   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  46 130 183 253 253 207   2   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  39 148 229 253 253 253 250 182   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0  24 114 221 253 253 253 253 201  78   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  23  66 213 253 253 253 253 198  81   2   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0  18 171 219 253 253 253 253 195  80   9   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0  55 172 226 253 253 253 253 244 133  11   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 136 253 253 253 212 135 132  16   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]]

なんとなく、数字「5」の画像ということがわかりますね。

y_train:学習用の画像データに対する答え
y_test:テスト用の画像データに対する答え

画像データの対となっていて、0 ~ 9 の数値(答え)が入っています。

こちらもイメージしやすいように10件ほどデータを抜き出してみました。

[5 0 4 1 9 2 1 3 1 4]

1つめの画像の答えは「5」。2つめの画像の答えは「0」・・・
という感じのデータになります。

学習用のデータは全部で60000データの配列になっており、
テスト用のデータは全部で10000データの配列になっています。


次の処理は、データを整形しています。

X_train = X_train.reshape(X_train.shape[0], 784)[:6000]
X_test = X_test.reshape(X_test.shape[0], 784)[:1000]

reshape メソッドで28x28の2次元配列を784の1次元配列に変換し、
学習用データは先頭の6000件以降を切り捨て。
テスト用データは先頭の1000件以降を切り捨て。
という処理になっています。


次の処理も、データを整形しています。

y_train = to_categorical(y_train)[:6000]
y_test = to_categorical(y_test)[:1000]

これは、答えのデータをベクトルデータに変換しています。

イメージしやすいように例で書くと、答えのデータが「5」だった場合、
以下のようなベクトルデータに変換しています。

[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]

こちらも学習用データは先頭の6000件以降を切り捨て。
テスト用データは先頭の1000件以降を切り捨て。
という処理になっています。

※データを切り捨てているのは、データ量が多すぎて時間がかかってしまうからだと思います。

ちょっと長くなってきましたので、続きは次回とします。

今日はこのあたりで。ではまた~。

2018年7月26日木曜日

ディープラーニングを体感しよう:第4章(ディープラーニングとは?)



お久しぶりです。よっしーです。


これまでの記事:
ディープラーニングを体感しよう:第1章(まずは環境構築)
ディープラーニングを体感しよう:第2章(Python環境を構築する)
ディープラーニングを体感しよう:第3章(プログラムを動かしてみよう)


前回から少し時間が空いてしまいました。

本業が忙しく、記事をまとめる時間がなかなか取れませんでしたが、

今週からは投稿復帰しますので、またまたよろしくお願いします。


前回は、実際にプログラムを動かし、内容を表示するところを見ました。

今回は、そもそもディープラーニングってどんなものなのだろう?

という内容を記載して行きたいと思います。


最近「機械学習」という単語を良く聞くかと思います。

機械学習:
 人工知能における研究課題の一つで、人間が自然に行っている学習能力と同様の機能を
 コンピュータで実現しようとする技術・手法のこと

ディープラーニングというのはこの機械学習の中の1つにあたりますが、

機械学習にもいろいろと分類があり、

私が理解している内容は以下となります。


「機械学習」の1つとして「教師あり学習」がある



教師あり学習:
 機械学習のアルゴリズムの1つ。事前に例題と答えのデータを与えておき、
 それを元に学習し、答えを導く手法。


「教師あり学習」の技法の1つとして「ニューラルネットワーク」がある



ニューラルネットワーク:
 機械学習の技法の1つ。脳機能に見られるいくつかの特性を計算機上のシミュレーションによって
 表現することを目指した数学モデル。


「ニューラルネットワーク」を利用した機械学習手法として「ディープラーニング」がある



ディープラーニング:
 多層にニューラルネットワークを重ねて特徴を捉え、答えを導き出す機会学習の技術、手法。


ウィキペディアなどを見ても、専門用語が多く、なかなか理解しにくにので、
素人なりに、機械学習から掘り下げて、まとめてみました。

今日はこのあたりで。ではまた~。

2018年7月20日金曜日

IBM Cloud上でFlaskを使用してWebAPIを作る(後編)

前回、JSONデータをやり取りするWeb APIを作成しましたが、{"user":"太郎"}のように日本語を指定するとエラーが発生します。
ログを確認すると、


user = str(request.json['user'])
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)


というエラーが出力されていました。

ググってみると「str文字列」だの「unicode文字列」だの・・・
ん?それってPython2の話ですよね?

もしやと思い、Pythonのバージョンを出力して確認してみると、やはりPython2.x系でした。

import sys
print('{}.{}.{}'.format(sys.version_info.major, sys.version_info.minor, sys.version_info.micro))

> 2.7.13


runtime.txtというファイルを新しく作成し、そこに

python-3.6.2

と記述してバージョンアップすると、エラーなく日本語も扱えるようになりました。

またいつか、どこかで。

2018年7月13日金曜日

IBM Cloud上でFlaskを使用してWebAPIを作る(前編)

IBM Cloud上でFlaskを使用し、JSONデータをやり取りするWeb APIを作成しています。
その方法をメモ。

Starter Kitsの中から「Python Flask」を選択し、アプリケーションを作成します。


























作成したアプリのソースをダウンロードします。

PythonもFlaskも未経験ですが、いろいろ調べながら下記のようなコードを作成しました。
受け取ったデータを結果とともにそのまま返すだけです。

from flask import Flask, jsonify, request

@app.route('/api/sample', methods = ['POST'])
def Sample():
    if request.is_json:
        if 'user' not in request.json:
            user = ''
        else:
            user = str(request.json['user'])
        return jsonify({'status':'success', 'user':user})
    else:
        return jsonify({'status':'error'})


{"user":"Taro"}というデータを送信したところ、内部エラーが発生しました。

FlaskのAPIドキュメントの「is_json」の項には「New in version 0.11.」と記載されています。
requirements.txtは「Flask==0.10.1」と記載されており、どうやらFlaskのバージョンが古いことが原因のようです。

「Flask==1.0.2」と書き換え、現時点の最新版にバージョンアップすると、{"status":"success","user":"Taro"}という結果が返ってくるようになりました。

またいつか、どこかで。

2018年7月6日金曜日

申請用総合ソフトを使って登記申請してみた!

今年の株主総会で取締役の任期満了を迎え、その場で選任が決議され、取締役重任と相成りました。
重任でも法務局に変更登記が必要です。調べてみるとオンライン申請できるようなのでチャレンジしてみました。


申請するには


以前、社会保険関係はe-Govから、納税証明書取得時はe-Taxから申請しましたが、法人登記はまた別のシステムを利用することになります。それが

「登記・供託オンライン申請システム(登記ねっと・供託ねっと)」

です。
ただし、登記事項証明書の交付請求などはサイトからできますが、今回行う法人登記申請など大半の手続きは「申請用総合ソフト」というソフトを利用しなければなりません。


準備


まず、「申請用総合ソフト」を「登記・供託オンライン申請システム」からダウンロードしてインストールします。
インストールでは特につまずくことはありませんが、あとで参考にするので、インストール手順が記載されている「かんたん事前準備ガイド」という操作手引書はダウンロードしておきましょう。

「申請用総合ソフト」を起動してみましょう。


そうです。このソフトは申請者登録しないと使えません。
「かんたん事前準備ガイド」の「申請者情報の登録」にしたがい、サイトでユーザー登録しましょう。

ユーザー登録が完了したら、ソフトを起動し、「かんたん事前準備ガイド」の「ICカードの切替設定」にしたがって、ICカード情報を登録したら準備完了です。


いざ申請!


申請用総合ソフトのメイン画面です。





























サイトには主な手続きごとに操作手引書が用意されています。
今回は「株式会社の役員変更の登記(全員重任)申請」を参考に、

  1. 申請書に情報入力
  2. 株主総会議事録・株主リストを添付
  3. マイナンバーカードで電子署名

といった手順を経て、申請情報を送信しました。

登録免許税は電子納付可能で、インターネットバンキングから初めてペイジーを使って納付しました。
すべてオンラインで完結するなんて素敵!・・・と思っていました、この時は。


ところが



処理状況は申請用総合ソフトで確認できるのですが、何日経ってもステータスが更新されません。
ちょうど一週間ほど経ったころ、法務局から電話がありました。

「議事録等は郵送してもらえましたか?」

添付した書類の原本が必要とのことでした。
オンラインで申請するメリットがないなあ、と思いながら、法務局へ書類を持参しました。


さらに


しばらくして、また法務局から電話がかかってきました。

「マイナンバーカードでは電子署名として認められません。」

どうやら「法人認証カード」というものでないといけないようです。
見逃していただけかもしれませんが、そのあたりもマニュアルに分かりやすく書いておいてくれたらいいのですけどね。

結局、申請を取り下げ、再度書面で申請することになりました。
申請は申請用総合ソフトで取り下げることができます。その際にも電子署名が必要で、それはマイナンバーカードでもいいそうです。(そこはええんかいっ!)


扱う情報の重要性もあり、完全なオンライン化が難しいのかもしれませんが、窓口での対応も含めて、旧態依然としてるなあと感じました。

またいつか、どこかで。