OmniAICreator/Qiita-1.07M huggingface dataset:
fairseqで自分でトレーニングしたTransformerモデルをロードする

# はじめに

機械翻訳のTransformerモデルをトレーニングする機会があり，Pytorchベースのfairseqを使ったんですが，アプリ用のコードでモデルのロードにハマってしまいました．備忘録のために記事を書きます．

# fairseqとは

Facebookの人工知能研究チームが開発している，機械翻訳用のフレームワークです．Facebookが開発元ということもあり，Pytorchがベースになっています．最近はHuggingfaceのTransformersが人気でTransformerモデルを扱うならPytorchだよね，ということもあり，こちらをフレームワークとして選びました．
その他の機械翻訳フレームワークとしては，MarianNMT，OpenNMT（こちらもPytorchベース）などがあります．基本的な機能はどのフレームワークも大差ない印象ですが，論文実装のコードはfairseqが選ばれている場合が多いです．

# モデルのトレーニング方法

fairseqは<a href="https://fairseq.readthedocs.io/en/latest/">ドキュメント</a>が充実しているため，チュートリアル通りにやれば，自分でも機械翻訳モデルをトレーニングすることができます．チュートリアルは英語のみですが，日本語のドキュメントが不足しているのは，他の機械翻訳フレームワークでも同様です．

```ruby:トレーニングのためのコード（fairseqの公式ドキュメントから）
> mkdir -p checkpoints/fconv
> CUDA_VISIBLE_DEVICES=0 fairseq-train data-bin/iwslt14.tokenized.de-en \
    --lr 0.25 --clip-norm 0.1 --dropout 0.2 --max-tokens 4000 \
    --arch fconv_iwslt_de_en --save-dir checkpoints/fconv
```

トレーニングコードの`save-dir`は学習済みモデルの格納フォルダですが，このフォルダには，各エポックにおける学習済みモデル（`checkpoint(n).pt`），精度が一番よかった学習済みモデル（`checkpoint_best.pt`），最終エポックにおける学習済みモデル（`checkpoint_last.pt`）が格納されます．


```ruby:checkpoints_fconv
$ ls -alF
checkpoint1.pt
checkpoint2.pt
...
checkpoint99.pt
checkpoint_bes.pt
checkpoint_last.pt
```

推論の際は，`checkpoint_best.pt`を読み込むことになるかと思います．

# インタラクティブモードでの推論

fairseqの公式ドキュメントには，シェル上のインタラクティブモードでの推論についてはチュートリアルがありますが，Pythonのコード内でモデルをロードする方法などは紹介されていません．

```ruby:fairseq-interactiveによ推論（fairseqの公式ドキュメントから）
> MODEL_DIR=wmt14.en-fr.fconv-py
> fairseq-interactive \
    --path $MODEL_DIR/model.pt $MODEL_DIR \
    --beam 5 --source-lang en --target-lang fr \
    --tokenizer moses \
    --bpe subword_nmt --bpe-codes $MODEL_DIR/bpecodes
| loading model(s) from wmt14.en-fr.fconv-py/model.pt
| [en] dictionary: 44206 types
| [fr] dictionary: 44463 types
| Type the input sentence and press return:
Why is it rare to discover new marine mammal species?
S-0     Why is it rare to discover new marine mam@@ mal species ?
H-0     -0.0643349438905716     Pourquoi est-il rare de découvrir de nouvelles espèces de mammifères marins?
P-0     -0.0763 -0.1849 -0.0956 -0.0946 -0.0735 -0.1150 -0.1301 -0.0042 -0.0321 -0.0171 -0.0052 -0.0062 -0.0015
```
# Pythonのコード内で学習済みモデルをロードする方法

modelsクラスを使うのが正解でした．インタラクティブモードの場合と異なり，いくつかの引数は自動でロードされるようです．

```ruby:
>>> from fairseq.models.transformer import TransformerModel
>>> model = TransformerModel.from_pretrained('wmt14.en-fr.fconv-py', 'model.pt', 'wmt14.en-fr.fconv-py')
>>> text = 'Why is it rare to discover new marine mam@@ mal species ?'
>>> model.translate(text, beam=5)
'Pourquoi est @-@ il rare de découvrir de nouvelles espèces de mammifères marins ?'
```

# まとめ

fairseqは日本語ドキュメントが少ないですが，HuggingfaceのTransformersを使っている人であれば使いやすいですし，Pytorchベースということにも将来性を感じます．
論文実装のコードも多いですし，今後も触っていきたいフレームワークですね．
micro:bit v2のケースがないからMI:pro保護ケースを加工してみたら・・・

人生初のAdvent Calendar！
工作を含む内容なので、やってみたいと思う方がいるかわかりませんが、いつにしようか悩んで、土日にチャンレンジしてもらえるように、金曜にしてみました^^;

さて本題。
micro:bit v2を購入して、むき出しはちょっと・・・と思っていました。
v2用のケースを探してみましたが、見当たらず・・・
じゃぁ、MI:pro保護ケースをなんとか使ってやろうと思いました。
まぁ、スピーカが追加されたりしているので、そのままでは使えないので、ミニ四駆の改造で培った技術で加工しました。

穴をあけて、くりぬいたらこんな感じ。
比較のためにまえのバージョンも並べて比較。
![P_20201128_175033.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277984/ce3b9f02-dd98-706b-7fde-c0f5b239545e.jpeg)

この状態だと格好悪いので、ヤスリで調整・・・
でこんな感じ
![P_20201128_185420.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277984/c119fdf9-ba7d-1847-9713-4c64027f8681.jpeg)

ちょっときれいな四角ではないですが、まぁ、さっきに比べたらマシになりました。
この状態で、以下のようにメロディ鳴らしたり、音がしたときにアイコン出したりするプログラムを作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277984/70e3e02b-07d2-69d0-fc68-1d7a28d14bb1.png)

だがしかし！
音をほぼ常に拾う状態に。
ケースを外すと改善されるんですが、ケースを付けるとダメ・・・・
これはマイクがケースに覆われてしまうせいか？ということで、追加の穴をあける。

![P_20201128_231840.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277984/51c74f77-0431-a31e-5c4f-1f1a29dc002b.jpeg)

わりとキレイに穴が開いたので、試してみましたが・・・ダメです・・・

とりあえず、音はいったん置いといて、次はセンサーに触れないのでセンサー部分をカット。

![P_20201128_231829.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277984/e19bc5ab-9d4f-1a7b-2989-8922f4de7593.jpeg)

まぁ、若干曲がってるけど、センサーに触れるのでOK

というわけで音をどうするか・・・
考えた結果、こうします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277984/2feeddf7-8aca-11be-34c4-c359057c4f81.png)

変数で制御ｗ
物理的にどうこうするより、プログラムでなんとかするのが手っ取り早い。
仕事でハード制御していた時も、物理的に難しい場合はソフトで解決してたなぁ・・・(遠い目)

ちなみに、スピーカー使いながら音を取るときは、ケースの有無に関係なくこうしたほうが良いのではないかとちょっと思っています。

というわけで、micro:bit V2を保護したい方はこういった方法もあるよという紹介でした！
もし、MI:pro 保護ケースを使いたい人の参考になれば幸いです。
深層学習 Day 4 - 物体検知、セグメンテーション のまとめ


この記事は個人的なお勉強用のメモです。

# 講義

講義無し。
完全な自習。


# 関連記事

## 物体検知

### 概要

物体検知（detection）

与えられた画像から、
・**どの位置（矩形での範囲）**に
・どんな物体が
写っているのかを検知する技術。

1枚の画像から複数の物体を検知する場合も。

### 技術の種類

- Faster R-CNN
- YOLO
- SSD

### Faster R-CNN

#### 概要

R-CNN や Fast R-CNN を進化させた技術。
Fast R-CNN では Selective Search という技術を使っていたが
処理速度がネックになっていた。

Faster R-CNN では、RPN(Region Proposal Network) と言われる
小さな畳み込みネットワークで問題点を解決。

#### 構成

- 領域提案ネットワーク（Region Proposal Network, RPN）  
特徴マップを畳み込み層から受け取り、候補領域の座標とその「領域が物体である確率を出力。
- Fast R-CNN  
畳み込み層から受け取った特徴マップとRPNから受け取った候補領域を用いて、  
詳細な物体位置（バウンディングボックス座標）とその物体のクラスを出力。

RPN
reg layer：あらかじめ設定されたアンカーボックスの座標を予測（回帰）
cls layer：各アンカーボックスが物体か背景かを予測（2値分類）

#### アンカーボックス
それぞれ異なる**スケールおよびアスペクト比**を持つ矩形領域

##### 判定

正例（物体）のアンカーボックス：
　各正解ボックス（ground truth）との IoU が最大のアンカーボックス
　または、いずれかの正解ボックスとの IoU が 0.7 を超えるアンカーボックス
負例（背景）のアンカーボックス：
　どの正解ボックスとも IoU が 0.3 未満になるアンカーボックス
その他のアンカーボックス：
　損失関数を計算する際に考慮されない。

※ **IoU (Intersection over Union)**：一致度を測る指標

##### アンカーボックスの個数
特徴マップが $(H, W, C)$ のとき、
アンカーボックスの個数は **$H \times W \times k$**

##### 損失関数

```math
L(\{p_i\},\{t_i\})=\frac{1}{N_{cls}}\sum_i L_{cls}(p_i, p_i^\ast)
+\lambda\frac{1}{N_{neg}}\sum_i p_i^\ast L_{reg}(t_i,t_i^\ast)
```

$i$：ミニバッチ内でのアンカーボックスのインデックス
$p_i$：アンカーボックスが $i$ が物体である確率
$p_i^\ast$：正解ラベル（アンカーボックスが正例（物体）の場合は 1、負例（背景）の場合は 0）
$t_i$：予測された座標ベクトル
$t_i^\ast$：真の座標ベクトル
$L_{cls}$：分類損失
$L_{reg}$：回帰損失


### YOLO

You Only Look Once

一枚の画像を特定サイズのグリッドに分割
その分割されたグリッドごとにクラス推定とバウンディングボックスの回帰を実施
（分類ではなく**回帰**であることが大きな特徴）


### SSD

Single Shot Multibox Detector
YOLO に類似した物体検出タスク用モデル
これも**回帰**であることが特徴

通常のCNN
入力層に近い特徴マップのサイズ ＞ 出力層に近い特徴マップのサイズ
（詳細な位置情報を持つ）　　　　　（詳細な位置情報を持たない）

SSD は**各層の大きさの異なる**特徴マップを利用して物体を検出

## セグメンテーション

### 概要

セグメンテーションでは物体の位置を**ピクセル単位**で特定
（物体検知では物体の位置を**矩形位置**で特定）

### 活用

自動車の自動運転
リアルタイムでセグメンテーションを実施

### 技術の種類

- 全畳み込みネットワーク（Fully Convolutional Network, FCN）  
セマンティックセグメンテーション（Semantic Segmentation）の代表的なモデル

FCN は 2020 年のシラバスに含まれていないため、
出題されないと思いたい。

### セマンティックセグメンテーション

#### 概要

- ピクセルごとにクラス分類を解く
- いくつかのピクセルが孤立して異なるクラスに分類される問題あり
- この問題は**条件付き確率場**（Conditional random field, CRF）による後処理で解決

#### Dice 係数

IoU では面積の差が大きいほど値が小さく評価されてしまうため、
代わりに Dice 係数で評価する。

Dice 係数の数式

```math
Dice(S_{true}, S_{pred})=\frac{2|S_{true}\cap S_{pred}|}{|S_{true}|+|S_{pred}|}
```

$|S|$：領域 $S$ の面積
$S_{true}\cap S_{pred}$：$S_{true}$ と $S_{pred}$ の共通領域

余談
2つの面積の平均に対する重なり部分の面積の割合ということであれば、
以下の式の方がわかりやすい気がする。

```math
Dice(S_{true}, S_{pred})=\frac{|S_{true}\cap S_{pred}|}{\frac{|S_{true}|+|S_{pred}|}{2}}
```


#### Dice 係数と IoU の大小関係

Dice係数 $\geq$ IoU

#### IoU（参考）

```math
IoU(S_{true}, S_{pred})
=\frac{|S_{true}\cap S_{pred}|}{|S_{true} \cup S_{pred}|}
=\frac{|S_{true}\cap S_{pred}|}{|S_{true}|+|S_{pred}|- |S_{true}\cap S_{pred}|}
```
Azure DevOpsでSeleniumを使ったシステムテストがエラーの場合に画面キャプチャを見る方法

#Azure DevOpsでSeleniumを使ったシステムテストがエラーの場合に画面キャプチャを見る方法
Seleniumを使ったシステムテストを作った場合、テストがエラーになった場合にその時の画面キャプチャが見られると便利です。特にAzure Devopsで動かした場合、実際の実行状況を見ることが出来ないので、画面キャプチャは重要な情報です。結論から言うとAzure DevOpsの設定は特に必要なくローカルでしかるべき設定をしておけば、それだけでエラーの場合に画面キャプチャを見ることが出来ます。

#Seleniumで画面キャプチャを生成する方法
先ず、Seleniumで実行している画面のキャプチャは、Seleniumの機能で撮ることが出来ます。RemoteWebDriverにGetScreenshotというメソッドがあるので、この戻り値のclassのメソッドでSaveAsFileにフルパスのファイル名を指定すれば任意の場所にその画面キャプチャが生成出来ます。

```C#
var screenshot = Driver.GetScreenshot();
screenshot.SaveAsFile(@"C:\temp\Capture.jpg");
```
#画面キャプチャを欲しいタイミングに限定する方法
この画面キャプチャは全テストで欲しいわけでありません。成功したテストの場合はいらないので、限定するにはテストの結果が分かる必要があります。これはTestContextを使えば取得できます。TestCleanupで、TestContextのCurrentTestOutcomeプロパティを見ればテストの結果も分かるし、またTestNameプロパティでテスト名も取れるので、この名前をファイル名にすれば自動的にユニークに出来ます。ただMSTestでTestContextを使う場合ちょっと癖があります。

#TestContextの設定
TestContextのインスタンスをプロパティで1個、staticフィールドで1個、合計2つ持つ必要があります。そして、ClassInitializeで、staticフィールドのTestContextにコピーして、実際に使う時は何も設定しないプロパティのTestContextを使います。プロパティのTestContextを使わずにTestCleanupで_testContextをチェックするとこのテストは何個回していても全て同じテスト名が来てしまいます。何故か何も設定していないプロパティのテスト名は更新されています。staticプロパティ1個だけにすると今度はテストが実行できなくなります。[stackoverflow](https://stackoverflow.com/questions/24249133/understanding-the-mstest-testcontext)にも書いてありましたが、この2個持ち以外の方法ではうまく行きませんでした。。。

```C#
public TestContext TestContext { get; set; }
private static TestContext _testContext;

[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
	_testContext = testContext;
	//TestContext = testContext;	//ｘ:フィールドには入れずにプロパティだけに入れると何故かテストが実行できない

[TestCleanup]
public void TestCelean()
{
	_testContext.CurrentTestOutcome	//ｘ:本来こっちで良い気がするが、このインスタンスは最初のテスト情報しか入らない
	TestContext.CurrentTestOutcome	//〇:本来こっちには何も入れてない気がするが、このインスタンスはその時動いたテスト情報が入る
```

#テストが成功しなかった時に画面キャプチャを添付する方法
さて、TestContextでテストの結果が取れるようになったので、あとはTestCleanupで、_testContext.CurrentTestOutcomeが成功の場合はreturnしてやります。成功「以外」の場合とすることで、タイムアウトや例外の場合なども対象となります。この状態でTestContextにAddResultFileすればそのファイルを関連画像として扱う事が出来ます。

```C#
[TestCleanup]
public void TestCelean()
{
    if (TestContext.CurrentTestOutcome == UnitTestOutcome.Passed) return;
    var screenshot = Driver.GetScreenshot();
    var screenshotFile = Path.Combine(Directory.GetCurrentDirectory(), $"{TestContext.TestName}.png");
    screenshot.SaveAsFile(screenshotFile);
    TestContext.AddResultFile(screenshotFile);
}
```
これで実際にテストが失敗した時にテストエクスプローラーでみるとこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100916/5935cbd1-029d-3f1d-55f8-b9800164bd25.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100916/bc1b529a-40d1-a2e9-0621-d41078816492.png)

#Azure DevOpsでエラーの場合に画面キャプチャを見る
この設定をしておけば、Azure DevOpsでテストタスクを実行するだけで、自動的にエラーの場合に画面キャプチャを見ることが出来ます！実際にPipelineで画像をみたい時は、Pipelineの結果画面で、1.Testsをクリック。実際にエラーになったテストが表示されるので、2.テスト名をクリック、3.Attachmentsをクリックすると4にエラーの場合の画面キャプチャが表示されます。便利！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100916/9800e77b-f549-4407-9c7d-dc5e712663fe.png)
firebaseのエラー"Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null, null)"の解決策

#firebaseを使ったgoogle認証
flutterでfirebaseauthを使ったgoogle認証を実装しようとしたら、
android環境で以下のようなエラーがでた。

```
E/flutter ( 4434): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] 
Unhandled Exception:PlatformException(sign_in_failed,com.google.android.gms.common.api.ApiException: 10: , null, null)
```

色々ググってみたら、fingerprintを登録すればいいと書いてあるので、
https://developers.google.com/android/guides/client-auth
の言う通りに下記を実行したけどうまくいかない、、、

```
keytool -list -v \
-alias androiddebugkey -keystore ~/.android/debug.keystore
```

#最終的な解決策
①android>gradle下にあるgradlewを右クリックして「Open in Terminal」を実行

![gradlew.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/832092/31d2fee3-4f6c-2cee-54ae-85b1a9ee0f96.png)

②新しくターミナルが立ち上がるので下記を実行

```
./gradlew signingReport
```

そうするとSHA1とSHA256でのキーが表示される。
それらをfirebaseの設定の「フィンガープリントを追加」で追記する。
![fingerprint.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/832092/c9c60c5b-49d2-4abe-7344-8fcc8d578a5e.png)
Djangoを久しぶりに触る人が基本を思い出すための記事(1/3)～ターミナル、urls.py、views.py～

##この記事の趣旨
以前はバリバリにDjangoを触っていたけど、最近触れてない。
基本はわかってる。環境構築もしてる。
久しぶりに仕事で触らんといけなくなったけど、基本的なことを忘れてしまった。
そんな方に向けての記事です。


##プロジェクトのスタート
作業フォルダまで移動し、ターミナル画面で以下のコマンドを打ちます。(Mac,Linux）

```Mac:ターミナル
$ django-admin startproject XXXX
```



##プロジェクト内でappを作成する
プロジェクトフォルダの直下（manage.pyがあるフォルダ）まで移動し、
以下のコマンドを打ちます。(mac,Linux)

```Mac:ターミナル
$ python3 manage.py startapp YYYY
```

##基本的なセッティング
プロジェクトを初めて記述する時は以下の点を修正します。
・INSTALLED_APPS
・LANGUAGE_CODE
・TIME_ZONE


```settings.py
INSTALLED_APPS = [
    'django.contrib.admin',         #デフォルトで記載されてる
    'django.contrib.auth',          #デフォルトで記載されてる
    'django.contrib.contenttypes',  #デフォルトで記載されてる
    'django.contrib.sessions',      #デフォルトで記載されてる
    'django.contrib.messages',      #デフォルトで記載されてる
    'django.contrib.staticfiles',   #デフォルトで記載されてる

    'YYYY'　#"manage.py startapp"で作成したappの名前を指定
]

LANGUAGE_CODE='ja'
TIME_ZONE='Asia/Tokyo'

```

##開発サーバー起動
プロジェクトフォルダの直下（manage.pyがあるフォルダ）まで移動し、
以下のコマンドを打ちます。(mac,Linux)

```Mac:ターミナル
$ python3 manage.py runserver
```

##urls.pyの役割
ルーティングを担当。
プロジェクトのurls.pyでは各appのurls.pyへ役割を渡してあげる。
（プロジェクトのurls.pyではappのルーティングを記述しない）

```python:プロジェクトのurls.py

from django.conf.urls import include

urlpatterns = [
    path('admin/',admin.site.urls),  #管理者用ページへのルーティング（Djangoの機能）
    path('',include('YYYY.urls')),   #各appのurlsへ役割を渡してあげる
]
```

```python:appのurls.py

from . import views  #後述するviews.pyをインポートします。

app_name = 'YYYY'
urlpatterns = [
    path('example/exmaple/',views.example,name='exmaple'),
]
```


>**path()の説明**
> ●第一引数はルーティングするURL。
>上の例だと、http://xxxxx.com/example/emample/にルーティングされる。
>indexの場合は第一引数を指定しない。例：path('',views.~~~~,name=''),
>●第二引数は、後述するviews.pyで指定する「関数名」か「class名」を指定する。classで指定するときは、.as_viewが必要。
>上の例では、views.pyの中のexampleという関数を実行するよう指定している。
>●第三引数でこのルーティングの名前をつける。
>


##views.pyの役割
レンダリングを担当。ロジックのメインとなる部分。

```python:views.py
@require_POST
def example(request):
    return TemplateResponse(request, 'example/example.html',{'text': text})
```
>**説明**
>●@require_POSTとは
>@require_POSTでHTTPメソッドがPOSTの時のみという指定ができます。
>@require_POSTを指定しない場合は、他のHTTPメソッドでも関数が実行されます。
>
>●レンダリングの関数
>上の例ではreturnでTemplateResponseを指定していますが、これ以外にも
>HttpResponseRedirect
>redirect
>render
>などで指定することができます。（違いが気になる方は各自調べてください）
>
>
>●requestとは
>Djangoが扱う変数です。
>変数の中はリクエストのあったHTTPメソッドなど(POSTやGET)が入っています。
>決まりごととして覚えておく。
>
>●TemplateResponseの引数
>第二引数でレンダリングするhtml（templatesフォルダに入ってるhtml）を指定。
>第三引数ではhtmlに渡す辞書型の変数を指定します。
>上の例では一つのデータを渡してますが、複数指定する場合は辞書型の形で記述します。
>



今日のところは以上。

[【次回記事】Djangoを久しぶりに触る人が基本を思い出すための記事(2/3)～templates（html）～
](https://qiita.com/taole33/items/dc9fec063cad4ff177aa)
深層学習 Day 4 - Transformer のまとめ

この記事は個人的なお勉強用のメモです。

# 講義

### NN 機械翻訳の問題点

長さに弱い。

理由
・翻訳元の文の内容をひとつのベクトルで表現
・文長と翻訳精度の関係性

資料の 2 つのグラフからわかるとおり、
Encoder-Decoder モデルの方が 統計的機械翻訳モデルよりも
BLEU スコアが低い。

### Attention（注意機構）

#### 概要

翻訳先の各単語を選択する際に、翻訳元の文中の各単語の
隠れ状態を利用
重みをすべて足すと 1

例
h1 は重めに
h2 は軽めに

これにより、翻訳元と翻訳先とで単語ごとに注意を払う。
文中のある単語の意味を理解する時に、文中の単語のどれに注目すれば良いかを表すスコアのこと。

#### 仕組み

- Query  
入力。検索したいクエリ
- Key  
Key の中から似た文章を検索  
正規化されたベクトルを出力
- Value  
正規化されたベクトルを文章にする

Key Value Attension とも。

### Transformer

#### 概要

- Seq2seq と同じく、Encoder-Decoder モデル
- RNN を使わない（**使うのは Attension のみ**）
- 並列化しやすい

#### 構造

Encoder と Decoder

##### Encoder 側

- Input Embedding
- Positional Encoding（1. 単語ベクトルに単語の位置を追加）
- Encoder
 - Multi-Head Attention（2. 複数のヘッドで行う Dot Product Attention、Self-Attention）
 - Add & Norm
 - Feed Forward（3. 単語の位置ごとに独立処理する全結合）
 - Add & Norm

##### Decoder 側

- Output Embedding
- Positional Encoding
- Decoder
 - Masked Multi-Head Attention（4. 未来の単語を見ないようマスク）
 - Add & Norm
 - Multi-Head Attention
 - Add & Norm
 - Feed Forward
 - Add & Norm
- Linear
- Softmax

#### Attention の種類

Source Target Attention（ソース・ターゲット注意機構）
　Query：Target
　Key：Source
　Value：Source

Self-Attention（自己注意機構）
　Query：Source
　Key：Source
　Value：Source


「バナナ」「が」「好き」
単語間の注意を求める。

#### Position-Wise Feed-Forward Networks（PFFN）

**位置情報を保持**したまま、順伝播させる。

#### Scaled dot product attention

全単語に関する Attention をまとめて計算する。

```math
Attention(Q,K,V)=softmax \Biggl(\frac{QK^T}{\sqrt{d_k}} \Biggr)V
```

※ $Q,K,V$ が式のどこに位置するかに注意。
※ $\sqrt{d_k}$ で割る理由は、割らない場合にソフトマックス関数の勾配が小さくなってしまうため。

```math
\begin{align}
Q・K^T&=
\begin{pmatrix}
q_1\\
q_2\\
q_3\\
\end{pmatrix}
\begin{pmatrix}
k_1 k_2 k_3
\end{pmatrix}
\\
&=
\begin{pmatrix}
q_1 k_1 & q_1 k_2 & q_1 k_3\\
q_2 k_1 & q_2 k_2 & q_2 k_3\\
q_3 k_1 & q_3 k_2 & q_3 k_3\\
\end{pmatrix}
\end{align}
```

```math
\begin{align}
Attention(Q,K,V)
&=softmax(QK^T)・ V \\
&=
\begin{pmatrix}
0.1 & 0.2 & 0.7\\
0.4 & 0.3 & 0.3\\
0.8 & 0.1 & 0.1
\end{pmatrix}
\begin{pmatrix}
v_1\\
v_2\\
v_3\\
\end{pmatrix}
\\
&=
\begin{pmatrix}
0.1v_1 + 0.2v_2 + 0.7v_3\\
0.4v_1 + 0.3v_2 + 0.3v_3\\
0.8v_1 + 0.1v_2 + 0.1v_3\\
\end{pmatrix}
\end{align}
```

#### Multi-Head Attention

重みパラメータの異なる8個のヘッドを使用

#### Decoder

- 6 層（Encoderと同じ）
- 自己注意機構とソース・ターゲット注意機構の両方
- 自己注意機構の key と value はエンコーダから、query はデコーダから。

#### Add & Norm

Add：Residual Connection
　入出力の差分を学習
　実装上は出力に入力をそのまま加算するだけ
　効果：学習・テストエラーの低減

Norm：Layer Normalization
　平均 0、分散 1 に正則化
　効果：学習の高速化

#### Positional Encoding

単語列の**語順情報**を追加
$\sin$ と $\cos$ を利用（0～1の範囲）

```math
PE_{(pos,2i)}=\sin\Biggl(\frac{pos}{10000^{2i/512}}\Biggr)\\
PE_{(pos,2i+1)}=\cos\Biggl(\frac{pos}{10000^{2i/512}}\Biggr)\\
```

※ かっこの中は同じ。違いは $\sin$ と $\cos$ のみ。

# 実装演習

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/c38dafea-a92e-0fe9-a4a2-9692f8ae1225.png)

「自分の」は正しいが、それ以降は微妙な翻訳。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/dabe6073-0b95-8c1d-e2f4-436ee287acf5.png)

こちらは BLEU の評価。
いいのか悪いのか判断しづらい。
マルチスケールシミュレーション特論まとめ



# Introduction

マルチスケールシミュレーション特論の講義内容などを自分なりにまとめる

また，以下記事を参考にRubyの基礎から順に学ぶ

-   [チャート式Ruby](https://qiita.com/daddygongon/items/6f38d9a04e127a7952a7)


# Lecture

-   [week12~week13] [Thor & Rubocop](https://qiita.com/evendemiaire/items/0cd1871720fe5d0e5ce5)
-   [week11] [Class化について](https://qiita.com/evendemiaire/items/bc360c0ff1c356b9258f)
-   [week10] [Recursion(再帰)とClass化の冒頭](https://qiita.com/evendemiaire/items/120d9ea4a1a6f64cda53)
-   [week9] [Assert&Rubular](https://qiita.com/evendemiaire/items/6faaf8d014ac8067ddbc)
-   [week8] [Rakeで自動化&Export](https://qiita.com/evendemiaire/items/4dbcfb1819fc23ac8ba9)
-   [week7] [Rubyのお勉強＜制御構造\_Ifとか＞](https://qiita.com/evendemiaire/items/4f9550981bd3d6017cdd)
-   [week6] [Rubyのお勉強＜変数とMethod＞](https://qiita.com/evendemiaire/items/8d6bfc813a1ce5534b02)
-   [week5] [Rubyのお勉強＜入出力編＞](https://qiita.com/evendemiaire/items/136726feb666d719639f)
-   [week4] [Qiitaへの記事の投稿とGithunへの共有](https://qiita.com/evendemiaire/items/e9f8fc12ec62e82f5b7a)
-   [week1~week3] [環境構築について](https://qiita.com/evendemiaire/items/f31a9d450988f228c62e)


# Assignment

-   [extra3] [Refactoringの感想(ほんとに感想だけ)](https://qiita.com/evendemiaire/items/29d9b7413acd0eb551de)
-   [extra2] [Google Recruit](https://qiita.com/evendemiaire/items/f7069a77b7432a3622a3)
-   [extra1] [Roman numerals](https://qiita.com/evendemiaire/items/57bf590840cb4da51009)


# Memo <span class="timestamp-wrapper"><span class="timestamp">&lt;2020-12-30 水&gt;</span></span>

2020年もいよいよ終わりですな．

皆さんはどうでした？終わりよければ全て良しといいますが，いかがでしょうか？

私はというと，実家に下宿先の鍵を忘れたので，部屋に入れませんでした． なので研究室で24日と25日を過ごす羽目に．．．

ん？知り合いの家に泊めてもらったらって？ いやいや，世間一般ではクリスマスなんぞというイベントがあるらしいので，おいちゃんは気を使ったわけですよ．

不要不急の外出は良くないよね！(震声) それに独り身でも寂しくない！だって仲間がたくさんいるから！(哀れ) ~~（正確には直近で増えた笑）~~

来年は本厄だから厄払いに行こうかしら．．．

これで講義も終わりということで，記事を見てくださった方もLGTMを押してくださった方も，ありがとうございました．

では皆様，どうかご自身のお身体にはお気をつけて．

良いお年を！



------
 - **source** ~/school/multi/my_ruby/grad_members_20f/members/evendemiaire/README.org
深層学習 Day 4 - Seq2Seq のまとめ

この記事は個人的なお勉強用のメモです。

# 講義

## BERT を理解するまでの流れ

1. Encoder-Decoder Model
2. Transformer (Encoder-Decoder x Attention)
3. BERT

## Seq2seq の概要

名前のとおり、
系列（Sequence）を入力として、系列（Sequence）を出力するもの

例
翻訳（英語→日本語）
音声認識（波形→テキスト）
チャットボット（テキスト→テキスト）

## Seq2seq の理解に必要なもの

RNN：再帰的
LSTM：RNNの問題点を解決

どちらもすでに学習済みのため、ここでは詳細は省略。

## 言語モデル

単語の並びに対して尤度（どれだけ起こり得るか）、
文章として自然か、を確率で評価

```math
argmax_{w\in V} P(I, have, a, w) 
```

I have a の後に続く単語は？
＝出力確率の最も高い単語は？

時刻 t-1 までの情報で、時刻 t の事後確率を求める

## Seq2seq

RNN が 2 つ連結したもの（Encoder RNN と Decoder RNN）
Encoder から Decoder に隠れ状態 h を引き継ぐ。

Decoder の output 側に正解を当てると、
教師あり学習できる。

### Teacher Forcing

正解ラベルを Decoder の入力にする方法。
Teacher Forcing を適用すると、連鎖的に誤差が大きくなるのを
防ぐことができる。

### BLEU

翻訳でよく用いられる指標（読み方は、ぶりゅう？）
前提は、「プロの翻訳者の訳と近ければ近いほどその機械翻訳の精度は高い」というもの。

# 実装演習

lecture_chap1_exercise_public.ipynb

#### はじめに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/87059ee0-5dfe-a385-72fe-dfe4376ae51e.png)

いきなりエラー発生。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/5e25a88f-bdeb-16e4-bea8-764a2cac9b9f.png)

上のように、wheel の 0.34.2 をインストールした後にランタイムを再起動したら
エラーは解消された。
ただし、以下のエラーが出るが、とりあえず気にせず無視する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/608a3400-9b28-052d-c945-e50a0255ec83.png)

#### 訓練セル

「# 訓練」と書かれているセルの実行に時間がかかる。

余談
講師が訓練セルを開始した数分後に自身で訓練セルを実行したが
自身の訓練セルの方が実行終了が早かった。
Google Colaboratory の処理性能は年々向上しているのだろう。

#### 英語から日本語に翻訳された文章

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/86a39e0c-99d5-95b8-2658-0f549a69fdf6.png)

講師の実行結果は「商売 の 世話 を し い 。」という意味不明な出力だが
こちらの出力は意味の通じる出力になっている。
しかし他の翻訳結果はひどい内容だった。


#### BLEU

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810819/2d5388e1-4198-5e9e-2221-dbf74285bc68.png)

この値がいい値なのかよくない値なのかはよくわかっていない。
IBM Cloud:（小ネタ）2つ目以降のInterfaceにFloating IPを割り当てる方法



2021/06/05 追記
Floating IPをeth0以外に付けるのは、UIでは今はできなくなっており、API・CLI のみで可能になったようです。CLIの場合は`ibmcloud is in-nic-ipc`を利用します。
eth0以外に割り当てるとルーティングテーブルを変更しないといけないため、（個人的には本当に余計なお世話だと思いますが）それに気づかずにeth0以外に付けた利用者が外部通信できなくなってしまうという混乱を避けるため、本当に分かっている人しか変更させないようにという配慮のようです。

#はじめに

ずっとFloating IP(FIP)は

1. １つのVSIに2つ以上のFIPは割り当てられない
2. 一番最初のPrimary Interface(eth0)にしか割り振れない

と思っていた。1については現時点でも正しく、確かにすでにFIPが割り当てられている状態で他のInterfaceにFIP追加の画面が出てこない。
2もそうだよなって思っていたら、GUIを見てみたら実際にはPrimary Interface(eth0)だけでなくSecondary Interface(eth1)でもFIPを選択できる構成になっていた。よって、実際に通信が可能かを試してみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/3a9edcea-df7c-bb8e-9fd6-64d37cf8dfe1.png)


（なお、少なくとも過去にはこういう画面は出てこなかった記憶があるし、Docsにも以下のような記載が本記事執筆時点（2020/11/29）にはある。）


> https://test.cloud.ibm.com/docs/vpc?topic=vpc-faqs-for-vsis&locale=en#faq-vsi-4
During floating IP assignment in a VPC, a customer must specify the vNIC of the instance, is that correct?
Yes, and in fact, it must be the primary network interface of a server.



#FIPのeth1(Secondary Interface)への割り当てと設定

やってみると、Customer Portal上では実際に確かに割り当て可能だった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/5300b72e-fd7e-0918-9a76-64ff8da4753a.png)

ただし、このままではFIP経由で通信はできないはずである。なぜなら、以下のようにprimary interfaceであるeth0がdefault gatewayになっているから。

```shell:ルーティング情報
[root@syasuda-dualnic ~]# ip r
default via 10.0.0.1 dev eth0
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.25
10.4.0.0/24 dev eth1 proto kernel scope link src 10.4.0.6
169.254.0.0/16 dev eth0 scope link metric 1002
```

よって、この設定を変更する必要がある。default gatewayをeth1のgatewayである10.4.0.1に変更するために、以下のような設定ファイルを作成する。

```txt:/etc/dhcp/dhclient.conf
interface "eth1" {
    supersede routers 10.4.0.1;
}
```

dhclientコマンドを利用してもいいが、OS再起動しても変わらないことを確認しておきたいので、OS再起動をして設定が反映されたことを確認する。

```shell:OS再起動後
[root@syasuda-dualnic ~]# ip r
default via 10.4.0.1 dev eth1
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.25
10.4.0.0/24 dev eth1 proto kernel scope link src 10.4.0.6
169.254.0.0/16 dev eth0 scope link metric 1002
```


#テスト

Secondary Interfaceにアクセスできるようになった！

```
Shinobu-no-MacBook-Pro:~ yasuda$ ssh root@162.xx.xx.xx
The authenticity of host '162.xx.xx.xx (162.xx.xx.xx)' can't be established.
ECDSA key fingerprint is SHA256:bYEv8UMsSudXINj9sWfPo/01Odfxt7TNzdsYwP5hh+8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '162.xx.xx.xx' (ECDSA) to the list of known hosts.
Last login: Sun Nov 29 05:41:11 2020 from 10.0.0.12
```

#おまけ
ドキュメント修正依頼中・・・・・・
フィボナッチ数列

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# Rubyでフィボナッチ数列


# フィボナッチ数列

フィボナッチ数列は以下の漸化式からなる．

    F(0)=0
    F(1)=1
    F(n+2)=F(n)+F(n+1) (n>=0)
    
    0,1,1,2,3,5,8,13,21...


# コード

メインコードはこれ

```ruby
require './assert_equal_richer_output.rb'
def fib(n)
  return 0 if n==0
  return 1 if n==1
  return fib(n-1)+fib(n-2)
end

[[0,0],[1,1],[2,1],[3,2],[4,3],
 [5,5],[6,8],[7,13],[8,21],[9,34]
].each do |index,expected|
  puts assert_equal(expected,fib(index))
end
```

前回のassert\_equal\_richer\_outputのコードはこれ

```ruby
require 'colorize'
def assert_equal expected, result
  p ['expected',expected]
  p ['result',result]
  if expected==result
    puts 'true'.cyan
  else
    puts 'false'.magenta
  end
end

if $PROGRAM_NAME == __FILE__
  assert_equal(1,1)
  assert_equal(1,2)
end

```


# class

コードは以下

```ruby
class Hello
  def initialize
    @name = gets_name
    puts_hello
  end

  def puts_hello
    puts "Hello #{@name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name
  end
end

Hello.new

```

"@name"でnameを暮らす変数にする．


# folding

emacsの場合C-c,h>>>folding

C-c,s>>>表示



------
 - **source** ~/grad_members_20f/members/Kenny0704/c10.org
現役高専生による学習環境のすゝめ

# はじめに
ども、現役高専生のMarnyです。

世の中がコロナによって、自粛をしていく中で僕自身の開発環境・学習環境というのが大きく変わりました。

今回は、僕が買ってよかったと思う物、これから買いたいなと思っている物を書いていきます。


## 買ってよかったもの

### [開発編]
#### Happy Hacking Keyboard Professional JP

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450534/ed5092c8-d033-14e3-9382-a1b096df34d9.jpeg" width="800">

引用：Amazon購入ページ
[Amazon購入ページ](https://www.amazon.co.jp/PFU-Keyboard-Professional-N%E3%82%AD%E3%83%BC%E3%83%AD%E3%83%BC%E3%83%AB%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC-PD-KB420B/dp/B001KWJTD6/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Happy+Hacking+Keyboard+Professional+JP&qid=1607226048&sr=8-2)

言わずとしれた、高級キーボード。Youtubeにて、たまたまHHKB(Happy Hacking Keyboardの略)のレビュー動画をみて、

「うわーーー欲しぃーーーーー！！」

と思い、使っていたキーボードも気に入っていなかったので、中古で15000円だったものを購入。
実際にこの記事もHHLBで書いているのですが、**これはマジでいい。**

とりあえずポコポコとした打鍵音が気持ちいい。なんとなく寿司打とかやりたくなるくらいに気持ちがいい。
とにかく、このキーボードを打ちたい意欲から、開発へのモチベーションに繋がりますね。

### Anker PowerPort 10
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450534/ccfeb62f-574d-892e-c8c2-0c2c7c28f464.jpeg" width="800">

引用：Amazon購入ページ
[Amazon購入ページ](https://www.amazon.co.jp/Anker-PowerPort-USB%E6%80%A5%E9%80%9F%E5%85%85%E9%9B%BB%E5%99%A8-%E3%80%90PowerIQ-VoltageBoost%E6%90%AD%E8%BC%89%E3%80%91/dp/B00YS3ZYWY)

USBポートが10個もある、だいぶパワーを感じられる見た目の一品。

Anker製品ということもあり、信頼性は高め。

いろんな充電コードを使う時に、圧倒的ポートの数の安心感。付属のコードも結構長めでい感じ。
PCデスクにぽんとあると、なにかと助かる。

### 100均にある洗い物を置く台
これに関しては画像なしです。すみません。

なんやそれって思うかもですが、実はまぁまぁ使える。

この台なんですが、洗った物をおいて乾かす台です。そのまんま。

これに、先程あげたAnkerの10ポートや、ラズパイ、その他もろもろ・・・
とりあえず、PCデスクの脇に置けて、色々おけるので、便利です。

### [勉強編]

#### iPad Air
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450534/9fe868fd-75fa-bc64-e852-8a56abeb447b.jpeg" width="700">
引用：Amazon購入ページ
[Amazon購入ページ](https://www.amazon.co.jp/Apple-iPad-Air-10-9%E3%82%A4%E3%83%B3%E3%83%81-Wi-Fi-64GB/dp/B08J6JS8TD/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=iPad+air&qid=1607232962&sr=8-5)

用途としては、学校でのノート代わり。僕の通っている高専では、iPadでの板書が許されているので、ノートアプリとApple Pencelを使っています。

ノートアプリは**Good Note4**や**Map note**といったすばらしいアプリもあります。

iPadを使っている上で、一番便利なのは**Air Drop**ですかね。マジで便利。

クラスの多くの人間がiPadを持っているので、書けなかったノートをAir dropで共有。写真をPDFに、PDFに書き込み。
マジで便利。

~~実際のところ、ノートアプリとAir Drop以外微妙なのは内緒~~


### まとめ

色々上げていきましたが、まじでおすすめなのはHHKBとiPadですね。
では。
bitcoin-cli で wallet バックアップのメモ


bitcoin core v0.20.1 とします.

# Wallet を dump

バックアップしたい場合.

```
$ bitcoin-cli dumpwallet dump.wallet
```

とします.

`$HOME./bitcoin` にある wallet.dat をそのまま使うでもいいような?

# Dump した wallet を import

full path である必要があります.
相対パスだと

```
error code: -8
error message:
Cannot open wallet dump file
```

とエラーがでます.

```
$ bitcoin-cli importwallet /path/to/dump.wallet
```

としましょう.


## 疑問点

bc1(Bech32) なアドレスを dumpwallet -> importwallet で別マシン(別環境)で読むと 1xxx (P2PKH)なアドレスになってしまう.
PostgreSQLのjsonbを使うときの落とし穴

皆さん、PostgreSQL使ってますか？
オープンソースRDBであれば、ほぼこれ一択。というプロダクトですよね。

と、まずはじめに MySQL 派に喧嘩を売ってみました。ちなみに当方は喧嘩を売られても買いません。

さて、 PostgreSQL にはJSONデータを格納するための `json`型と `jsonb` 型の2つがサポートされています。
一般的にはバイナリデータで保存される `jsonb` 型のほうがパフォーマンスが高いので、通常は `jsonb` 型を使うと思うのですが、 `jsonb` 型にはいくつかの落とし穴があります。今回はそれをお伝えします。

# jsonbの落とし穴

1. 同じキーが集約される。
1. キーが自動的にソートされてしまう。

になります。順番に見てみましょう。

## 同じキーが集約される。
JSONの事実上の仕様である [RFC 8259](https://www.rfc-editor.org/rfc/rfc8259.txt) によると

```
When the names within an object are not unique,
the behavior of software that receives such an object is unpredictable.
Many implementations report the last name/value pair only.
Other implementations report an error or fail to parse the object,
and some implementations report all of the name/value pairs, including duplicates.
```

（[上記の参考訳](http://www.asahi-net.or.jp/~ax2s-kmtn/internet/rfc8259j.html#section-4)）

```
オブジェクト内の名前が一意でなければ、そのようなオブジェクトを受け取るソフトウェアの動作は予測できません。
多くの実装は、最後の名前/値のペアのみを報告します。
その他の実装は、エラーを報告するかオブジェクトの解析に失敗しますが、重複を含むすべての名前/値のペアを報告する実装もあります。
```

となっており、キーの重複については許容されている。と読めます。

しかしながら、 `jsonb` 型にストアする場合は、重複キーは集約されます。ちなみにどの値が残されるのかは不定です。現在の実装（PostgreSQL 12）だと後勝ちのようですね。

```
insert into json_tables (data) values ('{"key": 1, "key": 2, "key": 3}');
select * from json_tables;
    data
------------
 {"key": 3}
(1 row)
```

これ自体はそういう実装でもまぁそうだよね。で済むんですが、次が厄介です。

## キーが自動的にソートされてしまう

なんと `jsonb` 型はストア時にキーがソートがされてしまいます。

```
insert into json_tables (data) values ('{ "c": "c", "a": "a", "b": "b"}');
select * from json_tables;
              data
--------------------------------
 {"a": "a", "b": "b", "c": "c"}
(1 rows)
```

これは `jsonb` 型ではハッシュの **順番が保持できない。** ということを意味しています。

本来ハッシュの順番は保証されないので冷静に考えれば当然ですが、見た目上の順番があるのでそれが保持されると思いがちです。
表示の順番がなんかおかしい。というバグの原因を探していたら実はこれだった。ということがありました。

特に配列とハッシュの区別が無いPHPプログラマーはその罠に陥りがちかも。
rubyのハッシュも1.9から順番が保証されるようになったので同じ罠に陥るかもしれません。
順番を保持したい場合は配列を使う必要があります。

ちなみに `json` 型であればこのような問題はありません。これは、入力されたデータをそのままテキストデータとして保持しているからです。
その代わり容量の効率や検索時のパフォーマンスが犠牲になります。

```
insert into json_tables (data) values ('{"key": 1, "key": 2, "key": 3}');
select * from json_tables ;
              data
--------------------------------
 {"key": 1, "key": 2, "key": 3}
(1 row)

insert into json_tables (data) values ('{"a": "a", "c": "c", "b": "b"}');
select * from json_tables ;
              data
--------------------------------
 {"a": "a", "c": "c", "b": "b"}
(1 rows)
```

こうやって `json` 型にするか `jsonb` 型にするかで悩めるのも PostgreSQl が MySQL に優れているところですね。
それでは良い PostgreSQL ライフを。
【RxSwiftの勉強メモ】#1「ボタンのタップを検知してラベルの内容を変更する」

#この記事の目的
RxSwiftの使い方を学んでいくために簡単なサンプルを作成し記録する。
後から見直して頑張ります。
↓にサンプルコードを示します。

#サンプル
```
import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {

    
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var badButton: UIButton!
    var numberofGood = 0
    
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        button.rx.tap
            .subscribe { (event) in
                self.buttonTapped()
            }
            .disposed(by: disposeBag)
        
        badButton.rx.tap
            .subscribe { (event) in
                self.badButtonTapped()
            }
            .disposed(by: disposeBag)
        
        label.text = String(0)
    }

    func buttonTapped() {
        
        numberofGood += 1
        label.text = String(numberofGood)
    }
    
    func badButtonTapped() {
        
        if numberofGood > 0{
            numberofGood -= 1
            label.text = String(numberofGood)
        }
    }
}
```
![スクリーンショット 2020-11-29 20.35.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412828/1e73b0c5-84e1-4a8e-1861-c2b439c510c4.png)


#サンプルコードの内容
サンプルコードは至ってシンプル。
画面左上のいいねボタンがタップされると画面中央の数値がインクリメントされ、
画面右上の悪いねボタンがタップされるとデクリメントされます。
![画面収録 2020-11-29 20.13.19.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412828/6404b4fd-5678-c3b2-f0cc-05173bb99478.gif)

#まとめ
RxSwiftを理解している人にとっては容易すぎる内容は承知の上で
引き続きメモ的な位置付けとして投稿していきたいと思います！。
1行編集で自分のプロジェクトでDaggerのAnnotation ProcessingをAndroid Studioでデバッグする

Daggerが内部でどんなモデルを作ってどんな処理をしているんだ。。ってなったり、エラーになって、中身のコードを読みにいって、この変数に何が入っているんだろう。。ってなったりすることが稀にあるのでメモしておきます。


appモジュールなどでcompileOnlyでkaptで使うコンパイラの依存関係を追加して、Android Studioが使っていデバッグしたいコードを見られるようにします。プロジェクトでの編集はこれだけです。デバッグでの利用が終わったら消してください。

```kotlin
dependencies {
    // compileOnlyで追加する
    compileOnly 'com.google.dagger:dagger-compiler:2.30.1'
    // hiltなら以下など
    compileOnly "com.google.dagger:hilt-android-compiler:2.29.1-alpha"
}
```

デバッグしたいコードをcommand + option + oなど(macでのFind simbolのショートカット)でブレークポイントつけたいクラス、処理を探してブレークポイントをつけます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/af367b11-5716-6fcd-81fd-cd121a5006d3.png)

configurationを開いて、EditConfigrations...をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/973a2e67-6ec1-e676-d728-ca40a58975da.png)
+ボタンから、Remoteを追加します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/daa63cc0-b912-c7be-6e8f-0eab031cf5a1.png)
Use module classpathを先程compileOnlyを追加したモジュールで追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/5a8bc1a8-50d7-abfc-3469-b69af5ff1261.png)

次にターミナルなどからデバッグしたいプロジェクトで実行したいモジュールやバリアントにして次のGradleビルドを動かします。(Kotlinなのでkaptになっていますが、Javaの方はそのタスクを指定してあげてください。)

> ./gradlew --no-daemon clean app:kaptDebugKotlin -Dorg.gradle.debug=true -Dkotlin.daemon.jvm.options="-Xdebug,-Xrunjdwp:transport=dt_socket\,address=5005\,server=y\,suspend=n"

このGradleビルドは最初の段階で実行されずに止まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/95861aa8-c80c-4032-6ed0-5e8add6cd9ea.png)


Android Studio上でRemoteのConfigurationが設定されているのを確認して、デバッグのアイコンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/77c3dd06-d11e-28f9-7db4-d86cd1e71f0d.png)
するとビルドが動き出して、止まってほしいところでデバッガーの実行を止めてデバッグすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/0e15d956-5712-0901-7b35-685d4eb26b00.png)

これは自分のプロジェクトである必要はなく、どのプロジェクトでもcompileOnlyを追加すれば確認できます。
またこれはDaggerに限定されず、さまざまな処理に応用できそうです。
docker-composeで都合の良いPython3実行環境を作成する

## 概要
* Python3の都合の良い実行環境が欲しくなったのでdockerで作成しました。
   * いつも使ってるOSがCentOS7だ（ubuntuではない。。）
   * ENVを切るのがめんどくさい。
   * 検証のたびにサーバを準備したくない。
   * 検証が終わったら消したい。

## 事前準備
* 下記をインストールし実行できること。
    * docker
    * docker-compose

## ディレクトリ構成

```
./---docker-compose.yml
  |--Dockerfile
  |--requirements.txt   # pipインストール用 利用しなければ不要
  |--.env               # 環境変数用 利用しなければ不要
  |--src                # pyファイルを配置するディレクトリ
      |-- sample.py
```

## 各種ファイルの配置
### `docker-compose.yml`
```docker-compose.yml
version: '3'
services:
  python3:
    restart: always
    build: .
    container_name: 'python3'
    working_dir: '/root/src'
    tty: true
    volumes:
      - ./src:/root/src
    env_file:
      - .env
```

### `Dockerfile`

```Dockerfile
FROM python:3
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
ADD requirements.txt /root/
RUN pip install -r /root/requirements.txt
```

### `requirements.txt`
* pipインストールする必要があれば記載する

```requirements.txt
requests
```

### `.env`
* 環境変数を設定する必要があれば記載する

```.env
SAMPLE_USER ='root'
```

### `sample.py`
```sample.py
print("hello world")
```

## 実行
### コンテナを起動
```
$ docker-compose up -d
```
### スクリプトの実行
* dockerホストになっているサーバからexecでpythonスクリプトを実行できる。

```
$  docker-compose exec python3 python3 sample.py
hello world
```

### requirements.txtや.envを修正したとき
* 一度停止して再ビルド

```
$ docker-compose down
$ docker-compose build
$ docker-compose up -d
```
GIT　 入門

# はじめてのGIT 
SESで使われる実務を見据えて必要最低限の知識を集めました。
私が考える必要最低限です。
# ？？？
Git→Githubに登録するときは
mainなんだろうか？
masterなんだろうか？

# コンテンツ
・用語
・TakeAway
・quiz
# 用語
・git・・・分散型バージョン管理システム
・github・・・・Gitをオンライン上で管理するサービス
・リポジトリ・・・・保管場所
・ローカルリポジトリ・・・・
・リモートリポジトリ・・・・
・CUI GUI・・・・
・modified・・・ 修正された
・fetch　・・・ 取って来る
# TakeAway
which git
git --version
mkdir firstrepo
ls
cd firstrepo
git init
ls -a
git config --global user.name "Gina Tanaka"
git config --global user.email gina-tanaka@kvf.biglobe.ne.jp
git config -l
touch Readme.md
○　git status
git add Readme.md
git commit -m "はじめてコミット"
○　git push origin
git log
git restore
## 切り替え
切り替え練習は下記のアドレスで
https://www.sejuku.net/blog/71457
補足
○　git branch
git branch -a 
注　リモートも見たい場合
マスターからメインへの変更


git push origin develop
git pull origin develop
## remoteとの繋がり
前提としては
Git hub上にプロジェクトがあること
メールアドレスパスワードなどの設定があること

git remote add origin http://xxxxxx.xxx/xxxx
git push origin master
# quiz
バージョン管理の状態を確認するためのコマンド　→
git を　pushする。→
ローカルブランチの一覧を表示する。　→

## 追記
targetは.gitignoreに入れてコミットしないようにする。
2回目以降
git pull
CSVをサクっとSDFに変換する


#はじめに
[SDFをサクっとCSVに変換する](https://qiita.com/kimisyo/items/bc391d451b90c819996b)の逆バージョン。

なぜこんなことをしたいかというと、SMILESが含まれたCSVの化合物データに対し、SDF形式でしか表現できない情報（3次元座標や原子プロパティ等）を付加したいため。


#仕様
- CSVの中のSMILESプロパティと、プロパティ項目を指定し、SDFとして出力
- 化学構造はSMILESを元に生成
- プロパティ項目は1つだけ指定可能(とりあえず機械学習の目的変数を１つ入れたいだけなので)


#ソース
```csv2sdf.py
import pandas as pd
from rdkit import Chem
import argparse


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("-input", type=str, required=True)
    parser.add_argument("-output", type=str, required=True)
    parser.add_argument("-smiles_col", type=str, default="SMILES")
    parser.add_argument("-target_col", type=str, required=True)
    args = parser.parse_args()

    # CSVの読み込み
    print(args.input)
    df = pd.read_csv(args.input)

    # SMILES列を取り出し
    smiles_list = df[args.smiles_col].values

    # target列の取得
    targets = df[args.target_col].values

    mols = []
    for i, (smiles, target) in enumerate(zip(smiles_list, targets)):
        # SMILESからmolを生成
        mol = Chem.MolFromSmiles(smiles)

        # Targetの値を設定
        mol.SetProp(args.target_col, str(target))

        mols.append(mol)

    # SDFへの出力
    sdf_wtr = Chem.SDWriter(args.output)

    for mol in mols:
        sdf_wtr.write(mol)

    sdf_wtr.close()

```

#解説
特になし。
3次元化したいとか、原子プロパティを埋め込みたい等したい場合は、ソース中のRDKitのmolオブジェクトに色々操作を加えてみてください。
mv　コマンドつかい方

mv ファイル 移動先ディレクトリ
こうすることによってmvコマンドでファイルを移動させることができる。
例
mv pink.jpg app/assets/images/

mv ファイル1 ファイル2 ファイル3 ディレクトリA

ファイルを複数同時にやることもできる

Linuxコマンドをちゃんと勉強して息を吸うように使用できるレベルにならないといけないなと感じた。
DbContextOptionsBuilderに”UseSqlite”が含まれていませんと言われた時の対処法

ASP.NET Coreのチュートリアルをこなしている最中に以下のようなコンパイルエラーが
発生した。

```
’DbContextOptionsBuilder' does not contain a definition for 'UseSqlite' and no accessible extension method 'UseSqlite' accepting a first argument of type 'DbContextOptionsBuilder' could be found (are you missing a using directive or an assembly reference?)
```

どうやら、'UseSqlite'とやらが’DbContextOptionsBuilder'に含まれていないとのが原因らしい。

# 対処法
対処方法は単純で、含まれていないのなら、インストールすれば良いとのことで、
ターミナルを開いて、以下のコマンドを実行するれなよい。

```
    dotnet add package Microsoft.EntityFrameworkCore.Sqlite
```
この状態でコンパイルをかけると問題なくコンパイルに成功した。

### 動作環境
　OS : macOS　Ver.10.15.17
　エディタ：VScode
JavaScriptで特定のキー入力をトリガーにしたい

## はじめに

[JavaScript Advent Calendar 2020](https://qiita.com/advent-calendar/2020/javascript) 17日目の記事です。

「マウスを使わずにキーボードだけで操作して効率UPしているぜ!」という人が一定数いそうなので、Webアプリを作るならキーボードだけでも操作できるようにしようかなと思っています。

## 作ったWebアプリに...

例えば自作のマークダウンメモアプリに、ショートカットキーで操作する機能を付けたくなったとします。

「Windowsなら`Ctrl + /`を、Macなら`Control + /`を押して、"マークダウン記法の一覧"を表示できるようにしたい。」

## イベントの取得

何かキーボードのキーが押されたことを検知するのは、とても簡単です。

```js
document.addEventListener('keydown', event => {
    // 変数eventの中身はKeyboardEventオブジェクト
    console.log(event);
});
```

ビューポート内にフォーカスが当たっていれば取得できます。

### キーの識別に使えるKeyboardEventのプロパティ

- key : ShiftキーやOptionキーによる変化を考慮して、キーを現す文字列を返します。
- code : 押されたキーそのものを現す文字列を返します。ただしJIS配列のキーボードでは、`[`の入力に対し`"BracketRight"`が出力されるなど直感的ではありません。今回はこれを使います。
- keyCode : 非推奨。キーを現す一意な数値を返します。
- which : 非推奨。keyCodeと同じ値が出力されます。
- charCode : 非推奨。2020年12月17日時点で、ChromeやFirefox、Mac Safariではどのキーを押しても0が出力されます。

## どのキーが押されたかを知る

手元にApple Keyboard A1843 EMC 3138(JIS配列)がありましたので、どのキーを押してどんな出力が得られるのかを調べてみました。
![キーボードの各キーによって取得できるコード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905700/25a6050b-f47d-3ce2-db40-f4cf2a8af271.png)
[KeyboardEvent.code](https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent/code)の取得結果は以下のSVGファイルに記してあります。

[code一覧を見る(外部サイト)](https://listful.vercel.app/asset/keyboard-A1843-EMC-3138.svg)

今回の場合は/(スラッシュ)なので、`event.code === "Slash"`で判定ができます。

さらにWindowsなら`Ctrl`キーを、Macなら`Control`キーを共に押していれば`event.ctrlKey`がtrueになるため、それも調べます。

## 試してみる

かなり簡素なコードではありますが、Chromeなどの開発者ツールで手軽に試してみてください。

```js
document.addEventListener('keydown', event => {
    if (event.ctrlKey && event.code === 'Slash') {
        // 処理を書く
        console.log('control + / です');
    }
});
```

---

参考リンク

- [keyCode が deprecated になってた | N E R](http://var.blog.jp/archives/70803410.html)
- [KeyboardEvent - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent)
【備忘録】ハマったところ、肝どころ

# herokuへのデプロイ
① herokuのCLIにログイン

$ heroku login
CLIをまだDLしてない場合 → Heroku CLI.
② デプロイの下準備
1) herokuにデプロイ先を作成（既に作成してある場合は2)へ）

```:terminalコマンド
$ heroku create デプロイ先の名
```

```:terminal
Creating ⬢ デプロイ先の名 done
https://デプロイ先の名.herokuapp.com/ | https://git.heroku.com/デプロイ先
の名.git
```

2) デプロイしたいディレクトリに移動

```:terminalコマンド
$ cd デプロイしたいディレクトリ
```

3) デプロイしたいディレクトリがherokuのデプロイ先と紐づいているかを確認

```:terminalコマンド
$ git remote -v　
```

＜紐づいている場合＞

```:terminal
heroku https://git.heroku.com/heroku上のデプロイ先の名 (fetch)
heroku https://git.heroku.com/heroku上のデプロイ先の名 (push)
```

＜紐づいていない場合＞
下記の表記が出現する

```:terminal
fatal: not a git repository (or any of the parent directories): .git
```

その場合は下記の手順で紐付けを行う（既に紐づいている場合は③へ）

```:terminalコマンド
$ git init　//空のgitディレクトリを作成
```


```:terminalコマンド
$ heroku git:remote -a heroku上のデプロイしたいディレクトリ名　//herokuのデプロイ先と
先ほど作成した空のgitディレクトリを紐付け
```

```:terminalコマンド
$ git remote -v　//ちゃんと紐づいたかどうか確認
```

```:terminal
heroku https://git.heroku.com/heroku上のデプロイ先の名(fetch)
heroku https://git.heroku.com/heroku上のデプロイ先の名(push)
```

③デプロイ方法

```:terminalコマンド
$ git add .
$ git commit -am "make it better"
$ git push heroku master
```

# npm err 対応

１）npm自体のアップデートをする。

```:terminalコマンド
$ npm install -g npm
```

2)既存のモジュールを削除する。

```:terminalコマンド
$ rm -rf node_modules
```

3)とりあえずキャッシュを消してみる

```:terminalコマンド
$npm cache clean
```

4)再度インストール

```:terminalコマンド
$ npm install 
```

成功しているファイルを上書きしてから、再度パッケージをインストールする
外部スクリプトの変数を取得する方法

途中だけどごめんねー

# この記事でできること
- 外部のスクリプトにある変数を取得できるようになる。

# 参考例
- Sceneにはplaneとcubeを設置して、それぞれにPublicの変数を設ける。

![a03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/54088d00-f271-0503-b35e-84be9179e8db.png)

- planeオブジェクト
    - testA.cs
    - 変数intTestAは10

![a01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/c9620481-736a-ad55-81e8-6d5cdb0e418a.png)

- cubeオブジェクト
    - testB.cs
    - 変数intTestBは20

![a02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/1a01e758-dfa3-6151-395f-2e1e5213d46d.png)


```testA.cs 
using UnityEngine;

public class testA : MonoBehaviour
{
    public int intTestA = 10;
}

```

```testB.cs
using UnityEngine;

public class testB : MonoBehaviour
{
    public int intTestB = 20;

    testA script;

    void Start()
    {
        script = GameObject.Find("Plane").GetComponent<testA>();
        Debug.Log(script.intTestA);
    }
}

```
Fusion 360にCSVから点をインポートする

Autodesk Fusion 360にはいつもお世話になっています. (教育機関ライセンス無料なので)

別途生成した座標データを含むCSVがあり, それを点としてインポートする方法がわからなかったのでメモを残します.
自分の用途的に, 同一平面内の点のインポートがスコープです.

#課題
Fusionにビルトインであるスクリプト(ImportSplineCSV.py)はCSVの座標をスプラインとしてインポートするもの > 余計なことをせずに点がいい

#目的
Pythonスクリプトで, CSVに含まれる座標を点としてxy平面のスケッチにインポートする

#入力するCSV
CSVの書式はカンマ区切りで, **1行に1つの点のx,y,z座標をいれる. (zは全て0)**

```input.csv
1.5,3.6,0
8.4,2.8,0
3.4,6.1,0
```

#スクリプト
フローとしては, ダイアログで指定したCSVファイルに対して, カンマ区切りをばらして座標を抽出し, ポイントとしてスケッチに追加する, という作業を各行に対して行います.

下記コードを.pyファイルに記入し, 適当な場所に配置します.
(自分の場合は `C:\Users\USERNAME\AppData\Roaming\Autodesk\Autodesk Fusion 360\API\Scripts` あたり)

あとはFusion 360を開き, 画面上部から `Tools > ADD-INS > Scripts and Ad-Ins...` と進み, My Scripts欄のプラスボタンを押してファイルを保存したディレクトリを指定すればOKです.
ディレクトリ追加直後にはスクリプトが反映されず, ウィンドウを閉じたり開いたりしていたら表示されるようになりました.

```ImportCSVPoints.py
import adsk.core, adsk.fusion, traceback
import io

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        title = 'Import points from csv'
        if not design:
            ui.messageBox('No active Fusion design', title)
            return
        
        dlg = ui.createFileDialog()
        dlg.title = 'Open CSV File'
        dlg.filter = 'Comma Separated Values (*.csv);;All Files (*.*)'
        if dlg.showOpen() != adsk.core.DialogResults.DialogOK :
            return
        
        filename = dlg.filename
        with io.open(filename, 'r', encoding='utf-8-sig') as f:
            root = design.rootComponent
            sketch = root.sketches.add(root.xYConstructionPlane)
            line = f.readline()
            data = []
            while line:
                pntStrArr = line.split(',')
                for pntStr in pntStrArr:
                    try:
                        data.append(float(pntStr))
                    except:
                        break
            
                if len(data) >= 3 :
                    sketchPoints = sketch.sketchPoints
                    point = adsk.core.Point3D.create(data[0], data[1], data[2])
                    sketchPoint = sketchPoints.add(point)
                line = f.readline()
                data.clear()
                
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

```

※未検証なのでわかりませんが… スケッチにxy平面を指定しているので, z座標に何か数字が入ったら動かないかもしれません. あるいは3次元スケッチになるのかな…? あまり使いこなせていないのでよくわかってないです.
検証された方がいればコメントにてご教授ください.

#余談
このスクリプトですが, 個数にして700弱の点をインポートするのに使っていますが, 問題なく動いています.

同様の方法で`SketchCircles`メソッドを使ってCSVから丸をインポートしようとしましたが, 200ぐらいに数を減らしてもFusionがフリーズしてしまい使い物になりませんでした.
[ここ](https://forums.autodesk.com/t5/fusion-360-api-and-scripts/draw-large-number-of-circles/td-p/9163269)を見る限り一般的な問題のようで, 回避するにはスケッチを分けるといいようです.

私の用途としてはインポートした座標を元にバルクに穴を開けたいだけだったので, 円としてインポートしなくても穴径は指定できたのと, スケッチを分けると後工程が面倒になると思ったので思い切って点としてインポートしました.
改めてA5M2ツール使い方確認

#はじめに
データベースのGUIツールはたくさんがあります。
・navicat
・A5M2
・dbeaver
・TablePlus
・MYSQL: Workbench
・PostgreSQL: pgAdmin
・Oracle: oracle developer tools

やはり普段はWorkbenchとA5M2を使う機会は多かったです。

#A5M2とは
全名：A5:SQL Mk-2 　読み方：エーファイブ・エスキューエル・マークツー
高機能かつ軽量な汎用SQL開発ツール / ER図ツール / フリーソフト

出典：https://a5m2.mmatsubara.com/

#対応DB
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/761734c9-5968-a37d-494a-130242a8b93b.png)


#主な機能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/24c00aa0-bc32-f22f-5e07-65bad7e76434.png)

#SQL
対応するDBに対して、データ閲覧、編集、検索結果のCSV保存、Export、Importなどはできます。
SQLの整形もできますので、使うとSQLのスタイルは統一できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/7c95c499-d092-d009-c435-78e0674be93d.png)

#ER図設計機能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/6d42259e-6e3f-4be0-cdf1-f33f8a1d18aa.png)

Entity定義、ドメイン編集にカスタムタイプの定義、共通列の定義、ＤＤＬ生成、Entity定義書の出力（Excel　OR　HTML）など

普通のER機能は対応できており、使いやすいと思います。

##Entity定義書例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/fdf345ce-3f8e-4020-5b1d-c286626b97bb.png)

##Entityの定義のコピー例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/3bf5b0f8-e24f-9614-ac76-d30fd6516e3f.png)

コピーしてExcelに貼り付けると、Excelに整形などもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/7eff616c-9dbc-61b0-581c-c6350344bedb.png)


以上
参考書の打ち込み＆朗読データを共有するための2掲示板と流れの提案

<h3>参考書の打ち込み＆朗読データを共有するための2掲示板と流れの提案</h3>

参考書のタイピングデータ(と朗読データ)の共有を行いやすくするための
2掲示板と流れを考案してみました

<hr>
追伸

⇒ラインのオープンチャット機能を次のように使えばもっと汎用的にデータ共有ができましたね...

1.ラインでオープンチャットルームを作成する
2.以下のような自分のもつデータリストのURLを1で作成したオープンチャットルームに送信
 ex: https://docs.google.com/spreadsheets/d/18CNlSOQlZLOeWgm0-1ZgRWjGXZ7K0PB2gOa0s9MVkzw/edit?usp=sharing

3.チャットでのリクエストに応じて適宜データをパスワードつけるなりして送受信する

参考URL
<a href='https://appllio.com/how-to-start-line-openchat'>LINE「オープンチャット」とは──基本の使い方と便利ワザまとめ | アプリオ</a>
<hr>
<h3>2掲示板のURL</h3>

参考書打ち込みデータの作成完了通知用掲示板URL1:https://sankouurcrtuuti.apage.jp/

参考書打ち込みデータ共有用ダウンロードリンク依頼＆通知掲示板URL2:https://sankouurdllinkreqandresp.apage.jp/

<hr>

<h3>参考書打ち込みデータの共有の流れ</h3>

参考書打ち込みデータの共有の流れは以下になります。

前提：参考書打ち込みデータ作成者A、打ち込みデータ受信者Bともに
参考書S1を所有している

1.打ち込みデータを作成した作成者Aが作成したデータに関する通知を
通知用のURL1にコメントする

2.作成完了通知のコメントを見た受信者Bが欲しいデータだった場合
ダウンロードリンク依頼&通知掲示板にダウンロードリンク作成依頼を
コメントに記述する

3.定期的に参考書打ち込みデータ作成者Aがダウンロードリンク依頼＆通知掲示板に自分の名前でキーワード検索をかけて、ダウンロードリンク作成依頼があれば、ダウンロードリンクを作成し（参考書S1に基づくパスワードによって圧縮済み)、ダウンロードリンク依頼＆通知掲示板にダウンロードリンクを作成したことをコメントに記述する

4.定期的に受信者Bがダウンロードリンク依頼＆通知掲示板に自分の名前で
キーワード検索をかけて、依頼に対してダウンロードリンクがされ次第データを
リンクからダウンロードする

5.受信者Bは参考書S1から得られるパスワードに従い、ダウンロードデータを
解凍し、データを利用する