生産性向上へのショートカット

業務プロセスなどの効率化ではなく、キーボードショートカットで生産性向上を図る話です。
業務プロセスなどでの生産性向上をご検討の方も、戻るボタンを押す前にご一読ください。

---
この記事は [リンク情報システム](https://www.lis.co.jp) の「[Tech Connect Summer 夏のアドベントカレンダー](https://qiita.com/dgkz/items/2862d5e6b77203a126b3)」のリレー記事です。
Tech Connect Summer は勝手に始める真夏のアドベントカレンダーとして、engineer.hanzomon という勝手に作ったグループによってリレーされます。
（リンク情報システムの[Facebookはこちら](https://www.facebook.com/lis.co.jp/)から）

---
# 目指すもの
働き方改革が叫ばれる中、労働時間は短くしながら成果物は増やすか現状維持が期待されます。
要は定時に帰ったり、有休をちゃんと消化しながら、生産性は上げていく必要があります。

**生産性向上なんて、もうやることないよぅ！**

**いえ、あります。
人のPC操作を見ていると気になるあれです。**

**ショートカットです。**


一般的なショートカットを全ての人が使えるようにすることで、会社全体、ひいては社会全体の生産性を底上げします。

また、ショートカットを多用する人は、自分で調べるなどして体に染み込ましているかと思いますが、**まだ馴染んでいないアプリを使っていく中でショートカットがリコメンドされる**と、結構うれしいですよね。

# ショートカットを使わないことによるダメージ
仮にマウス操作でなんらかの操作を行ったとします。これが２秒かかるとします。
１日５０回これが行われるとします。

　100秒/日　＝　２回　x　50秒

月２０日の営業日として、年に換算すると、一人６時間の時間をロスします。

　6時間/年　＝ 100秒　x　20営業日　x　12カ月

ショートカットを多用しない要員が300名存在する会社の場合、1,800時間。

　1,800時間/年　＝　6時間　x　300名

いわゆる工数にすると**年間12人月のロスになります**。（１日7.5時間として）

　12人月　＝　1,800時間　÷　7.5時間　÷　20営業日

~~驚愕です~~。なかなかです。ちょうど**社員１人分**ですね。
数字で示してみても、ショートカットを多用しない場合の経済損失と地球環境に与える影響は、もう無視できません。


# どのようにショートカットをお勧めするか
普段通りPCを操作しているときに、「これのショートカットないんかい！」って時や、ふとお勧めされたりするのが良いです。
またその時、**ショートカットを使うことで得する時間を教えます**。

以下、仕様の概要です。

- マウスクリックを監視
- クリックされたら周辺の画像をキャプチャ
- 画像分類の機械学習で、クリック操作した機能（操作）を推論
- ３回クリック操作したら、当該操作のショートカットを画面右下に通知
- ショートカットを使うと得する時間も一緒に表示（固定的に１回の操作で２秒とする）
- 毎回お勧めされるとウザったいので、おすすめ不要にできる

# 技術要素
当社はWindowsが基本なので C# & WindowsForm でツールを作成します。

- [Accord](http://accord-framework.net/)
　　C#でメジャーどころの機械学習ライブラリです。
　　Bag Of Visual-words で画像パターンを求め、
　　Support Vector Machine で分類します。

- 他
　　

# UI
UIで以下が出来るようします。

- 学習データとする画像を収集する
- 収集した画像を選別する
- 選別した画像を操作と紐づける（教師データを作成する）
- 学習する
- ショートカットをお勧めする（マウス監視の開始）

以下の感じのUIになりました。

##### 学習系の画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272860/4390d18c-c1f4-6772-9208-894d88ec9565.png)

##### おすすめ通知
![03_おすすめ通知.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272860/2f7da963-8fe7-0940-c826-8e20ffb290cd.png)


# コード
ポイントとなるコードです。

##### 学習の準備
画像をBOVWでベクトル化します。
そのベクトルと画像のラベル番号（操作の種類）を紐づける形でListに入れておく感じです。
最後にアプリを学習状態で再起動可能とするため、BOVWのデータを保存します。

```C#
/// <summary>
/// 学習の準備
/// </summary>
private void Prepare()
{
    var trainImgList = new List<Bitmap>();
    this.labelList = new List<int>();

    // 画像が置かれているディレクトリ名をクラス名としている
    // ディレクトリ配下の画像に、分類しておいた学習データが格納されている
    string[] dirs = Directory.GetDirectories(TRAIN_PATH + "/img", "*", SearchOption.TopDirectoryOnly);
    foreach (string dirPath in dirs)
    {
        // ディレクトリ配下の画像ファイルを学習用のリストに入れていく
        string[] files = Directory.GetFiles(dirPath, "*", SearchOption.TopDirectoryOnly);
        foreach (string trainImgPath in files)
        {
            trainImgList.Add(new Bitmap(trainImgPath));

            // 一緒にクラス名をラベル番号としてclassLabelNoListに設定する
            var classification = Path.GetFileName(dirPath);
            this.labelList.Add(classDict[classification]);
        }
    }

    // Bag of Visual-wordsで画像パターンでベクトル化
    this.bovw.Learn(trainImgList.ToArray());

    // 各画像のベクトルをリストに設定する（学習時に使用する）
    this.vectorList = new List<double[]>();
    for (int i = 0; i < trainImgList.Count; i++)
    {
        this.vectorList.Add(this.bovw.Transform(trainImgList[i]));
    }

    // BOVWのデータを学習済みデータとして保存
    Serializer.Save(this.bovw, BOVW_MODEL_PATH);
}
```

##### 学習
Accordのリファレンスを参考にして組みます。

```C#
/// <summary>
/// 学習
/// </summary>
private void Train()
{
    // SVM
    this.msvm = new MulticlassSupportVectorMachine<ChiSquare>(0, new ChiSquare(), this.classDict.Count);

    // 一対一多の学習アルゴリズム
    var smo = new MulticlassSupportVectorLearning<ChiSquare>()
    {
        // 逐次最小問題最適化法というのを用いて2次計画問題に対応する（理解薄い。。）
        Learner = (param) => new SequentialMinimalOptimization<ChiSquare>()
        {
            UseComplexityHeuristic = true,
            UseKernelEstimation = true
        }
    };

    // 学習データ
    var inputs = this.vectorList.ToArray();
    var outputs = this.labelList.ToArray();

    // 学習する
    this.msvm = smo.Learn(inputs, outputs);

    // キャリブレーション
    var calibration = new MulticlassSupportVectorLearning<ChiSquare>()
    {
        // キャリブレーションで使用するアルゴリズムを設定
        Model = this.msvm, Learner = (param) => new ProbabilisticOutputCalibration<ChiSquare>()
        {
            Model = param.Model
        }
    };

    calibration.ParallelOptions.MaxDegreeOfParallelism = 4;
    calibration.Learn(inputs, outputs);

    textBox1.Text += "学習が完了しました\r\n";
}
```
# 実際の動作

以下のようにマウス操作で行の挿入を繰り返すと、、、
![01_クリック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272860/3d9d2fdd-afd1-6990-5306-84bb14527042.png)

ショートカットのお勧めが通知されます。
同時に、得することが出来なかった時間の推測値を教えます。

![02_2_おすすめ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272860/898cacfb-9992-ee17-6354-574c728e26cf.png)



このツールを従業員のPCで動かすことにより、全体的な生産性向上を図る算段です。
当然、学習データの収集、学習済みモデルの共有など、会社で利用する際に欲しくなる構成にすることも可能です。

---
本ツールに興味を持たれた方は、製品版のご相談歓迎いたします。
（本記事はプロトタイプについての記事となります）
利用用途、環境に合わせたカスタマイズも可能ですので、お気軽に[リンク情報システム](https://www.lis.co.jp/inquiry)へご相談ください。
また、「[Tech Connect Summer 夏のアドベントカレンダー](https://qiita.com/dgkz/items/2862d5e6b77203a126b3)」の他の記事においても、様々なアプリやツールを紹介していますので、ご参照ください。

---
[リンク情報システム株式会社](https://www.lis.co.jp)では一緒に働く仲間を[随時募集](https://www.lis.co.jp/employ_top)しています！
また、お仕事のご依頼、ビジネスパートナー様も募集しております。[お気軽にご連絡](https://www.lis.co.jp/inquiry)ください。