OmniAICreator/Qiita-1.07M huggingface dataset:
Validation(評価データ)の分け方について

# Validation(評価データ)の分け方について

- **K-Fold**
<div style="text-align: center;">
    <img src="/attachment/6269dfcbece6fa80e19f663" width="80%">
    
</div>

<br>

ホールドアウトを除いたデータをランダムサンプリングによって k 個の塊（Foldと呼ぶ）に分割し、Fold の一つを検定データ、残りの Fold を学習データとする。上図のように、対象となる学習データと検定データを k 回組み替えてモデルの学習と検定を行う。

全データで検定（バリデーション）を行うことができるので汎化性能が高くなり、信頼性が高くなる。<br>各 Fold ごとのスコアから、データに偏りが発生しているか、発生しているとしたらどういう特徴があるかの Deep Dive がしやすい。<br>

一方で、データ量が大きい場合には時間がかかり、実装するのが現実的でない場合がある。

数値を予測する回帰問題において、データに時系列性やグループ性がない場合に利用する。

<br>


 
- **GroupKFold**
<div style="text-align: center;">
    <img src="/attachment/6269de02ece6fa80e19f5fd3" width="80%">
    
</div>

<br>

あるグループに属するデータが全て学習データや検定データの同一の Fold に含まれるように分割を行い、特定のグループに属するデータが学習データと検定データをまたがることがないようにする。

ある特定の人物や製造ロットなどのグループを過学習したモデルができてしまうリスクがを低減されるので、予測時のリークを防ぐことができる反面、計算時間が多くかかったり、ドメイン知識がないとグルーピングする基準などの設定が少し難しい場合がある。<br>また、グループ数が少ない場合は特定のグループの性質を過学習するリスクにも注意が必要になる。

”同一人物が繰り返し出てくる場合”、”同じ製造ロット”や”同じ国”などデータ内に特有のグループが存在し、学習データに含まれない未知のグループに対して予測したい場合に利用する。

<br>

- **Leave-one-out法**
<div style="text-align: center;">
    <img src="/attachment/6269e1f7ece6fa80e19f6a76" width="80%">
    
</div>

<br>

データの一つ（１行）を検定データとし、その他のデータを学習データとする。<br>これをデータの総数分だけ、対象となる学習データ・検定データを組み替えてモデルの学習と検定を行う（k分割交差検定の k が行数分になったケース)

データが少量であったとしても全てのデータを利用することができるので、学習用のデータ量が増加するほか、検定を細かく行えるので、汎化性能を高めることができる反面、データ総量分だけ分割しているので、計算時間がk-foldよりさらにかかる。

データ数が少なく、データ全体を有効活用する必要があるケースで利用する。

<br>



- **StratifiedKFold**
<div style="text-align: center;">
    <img src="/attachment/6269dca2ece6fa80e19f5b2a" width="80%">
    
</div>

<br>

ホールドアウトを除いたデータを k 個の Fold に分割する際、Fold 内のカテゴリ分布（例：ポジティブクラスとネガティブクラスの割合）がなるべく一致するようにサンプリングを実施する。

未知のデータも同様であるという仮定が成り立つのであれば良好な検定スキームになる反面、データや課題の特性を考慮せずに層化抽出を行うとリークが発生したり、実は母集団と同一のカテゴリ分布ではなくてデータに偏りが発生する場合がある。

分類問題のように、パーティション毎のカテゴリ分布が重要なケースにおいて利用する。

<br>



- **Stratified Group k-Fold**
<div style="text-align: center;">
    <img src="/attachment/6269db15ece6fa80e19f5675" width="80%">
    
</div>

<br>

層化抽出と Group k-Fold を合わせた手法。<br>特定のグループに属するデータが全て一つの Fold に含まれるようにデータ分割を行ない、学習データと検定データにまたがることがないようにしつつ、Fold 中に含まれているカテゴリー値の割合も同一にする層化抽出を行う

グループ性と分類問題の両方を考慮することができる反面、計算時間が多くかかったり、層化抽出法と同様にデータが母集団と同一でないと偏りが発生する可能性がある。

グループ性を持ちつつ、分類問題で割合が重要なケースにおいて利用する。

<br>

 - **TimeSeriesSplit**
<div style="text-align: center;">
    <img src="/attachment/6269d830ece6fa80e19f48aa" width="80%">
    
</div>

<br>

時系列データを使った機械学習を行う際に、必ず過去のデータで学習して、それより未来のデータで検定を行うよう、データの時系列の順序性を考慮してデータを分割する。

必要以上に昔のデータなどを利用しないで学習を行うことができる反面、検定データの量が減少したり、データを十分に使うことができなくなる場合がある。



<br>**データのリーク(漏洩)**：予測したいターゲットに対して、本来未知であるべき答えとなるような値を使って学習を行うこと。<br>特に時系列問題においては非常に起こりやすい問題であるのでTimeSeriesSplitなどでの対処が必要。

<br>
<br>


- **手法の選定基準**

<div style="text-align: center;">
    <img src="/attachment/6269e157ece6fa80e19f6972" width="80%">
    
</div>

 <br><br>
>  参考サイト,画像の出典
><br> 
> https://www.datarobot.com/jp/blog/summary-of-ml-partitioning-part-2/
>
[OCI]Autonomous Database：Autonomous Databaseに接続したままHIGH/MEDIUM/LOW等の接続サービスを切り替える方法


# はじめに
Autonomous Databaseでは、同時実行性や処理の並列度の異なる接続サービスがあらかじめ複数用意されています。

https://blogs.oracle.com/oracle4engineer/post/adb-services-shares-201905

Autonomous Databaseに接続する際は、用意されている接続サービスの内のいずれか一つを選択して接続を行いますが、処理の特性によっては接続後に接続サービスを切り替えて、同時実行性や処理の並列度を変更したいケースがありえます。

今回は、Autonomous Databsaeに接続した状態で接続サービスを切り替える方法を紹介します。

# 1. Autonomous Databaseへの接続
SQL*PlusからAutonomous Databaseに接続します。
ここでは接続サービスとしてMEDIUMを指定して接続しています。
```
[opc@swingbench ~]$ sqlplus admin/XXXXXXXXXXXX@atp1_medium

SQL*Plus: Release 21.0.0.0.0 - Production on 月 10月 31 10:51:23 2022
Version 21.7.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: 月 10月 31 2022 10:50:59 +09:00


Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.17.0.1.0
に接続されました。
SQL>
```

# 2. 接続サービスの確認

SYS_CONTEXTファンクションを使用して、接続ユーザと接続サービスを確認します。
```
SQL> col session_user for a15
SQL> col service_name for a60
SQL> SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') session_user, SYS_CONTEXT('USERENV', 'SERVICE_NAME') service_name  FROM DUAL;

SESSION_USER	SERVICE_NAME
--------------- ------------------------------------------------------------
ADMIN		    XXXXXXXXXXXXXXX_DB202204211052_medium.adb.oraclecloud.com

SQL>
```

adminユーザとして、MEDIUMの接続サービスを使用してAutonomous Databaseに接続していることが確認できました。

# 3. 接続サービスの切り替え

接続サービスの切り替えには、CS_SESSIONパッケージ内のSWITCH_SERVICEプロシージャを使用します。
```
EXEC CS_SESSION.SWITCH_SERVICE('接続サービス（HIGH/MEDIUM/LOW/TP/TPURGENT）');
```
接続サービスをHIGHに切り替えてみます。
```
SQL> EXEC CS_SESSION.SWITCH_SERVICE('HIGH');

PL/SQLプロシージャが正常に完了しました。

SQL>
```
SYS_CONTEXTファンクションを使用して、接続サービスを確認してみます。
```
SQL> SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') session_user, SYS_CONTEXT('USERENV', 'SERVICE_NAME') service_name  FROM DUAL;

SESSION_USER	SERVICE_NAME
--------------- ------------------------------------------------------------
ADMIN		    XXXXXXXXXXXXXXX_DB202204211052_high.adb.oraclecloud.com

SQL>
```
接続サービスがHIGHに変わっていることが確認できました。

接続サービスをLOWに切り替えてみます。
```
SQL> EXEC CS_SESSION.SWITCH_SERVICE('LOW');

PL/SQLプロシージャが正常に完了しました。

SQL>
```
SYS_CONTEXTファンクションを使用して、接続サービスを確認してみます。
```
SQL> SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') session_user, SYS_CONTEXT('USERENV', 'SERVICE_NAME') service_name  FROM DUAL;

SESSION_USER	SERVICE_NAME
--------------- ------------------------------------------------------------
ADMIN		    XXXXXXXXXXXXXXX_DB202204211052_low.adb.oraclecloud.com

SQL>
```
接続サービスがLOWに変わっていることが確認できました。

# 参考資料
[SYS_CONTEXT](https://docs.oracle.com/cd/F19136_01/sqlrf/SYS_CONTEXT.html#GUID-B9934A5D-D97B-4E51-B01B-80C76A5BD086)
[CS_SESSION.SWITCH_SERVICE](https://docs.oracle.com/cd//E83857_01/paas/autonomous-database/adbsa/cs-session-package.html#GUID-4894EED6-7CBA-47BC-B6F7-EF0B32553386)
損失関数、評価関数について

# 損失関数、評価関数について
- **損失関数（Loss function）**
<br>
<div style="text-align: center;">
    <img src="/attachment/6268f2afece6fa80e19df13" width="60%">
     
図1:損失関数のイメージ
    
   出典：[https://atmarkit.itmedia.co.jp/ait/articles/2104/15/news030.html]
</div><br>

- モデルの学習時に、正解値とモデルによって出力された予測値とのズレの大きさ（これを「Loss：損失」と呼ぶ）を計算するための関数である。
- この損失の値を最小化／最大化することで、機械学習モデルを最適化する。
- ニューラルネットワークでは、損失関数は誤差逆伝播法（Back-propagation）と呼ばれる最適化の処理で用いられる
- 損失関数には様々なものがあり、予測する問題や用いるモデル、パラメータの求め方などによって用いる損失関数は変わってくる 

    -   平均二乗誤差 / Mean Squared Error(回帰)
    -   平均絶対誤差 / Mean Absolute Error(回帰)
    -   平均二乗対数誤差 / Mean Squared Logarithmic Error(回帰)
    -   交差エントロピー誤差 / cross entropy error(分類)
    
<br>

- **評価関数（Evaluation function）**
<br>
<div style="text-align: center;">
    <img src="/attachment/6268f7a3ece6fa80e19e13a8" width="60%">
     
図1:評価関数のイメージ
    
   出典：[https://zenn.dev/nekoallergy/articles/machinelearning-func]
</div><br>

- モデルの評価時に、モデルが出した【予測値】と実際の【正解値】がどれくらいズレているのかを計算するための関数
- 作った AI モデルが、どれくらい良い AI モデルなのかを評価するために使う
- 評価関数には様々なものがあり、予測する問題や用いるモデル、パラメータの求め方などによって変わってくる
<br><br>**回帰問題**
    - 平均絶対誤差（MAE：Mean Absolute Error）
    - 平均二乗誤差（MSE：Mean Squared Error）
    - 平均二乗誤差の平方根（RMSE：Root Mean Squared Error）
    - 平均二乗対数誤差（MSLE：Mean Squared Logarithmic Error）
    - 平均二乗対数誤差の平方根（RMSLE：Root Mean Squared Logarithmic Error）
    - 平均絶対パーセント誤差（MAPE：Mean Absolute Percentage Error）
    - 平均二乗パーセント誤差の平方根（RMSPE：Root Mean Squared Percentage Error） 
    
    **二値分類問題**
    - 正解率（Binary Accuracy）
    - 適合率（Precision）
    - 再現率（Recall）／感度（Sensitivity）
    - 特異度（Specificity）
    - F値（F-measure、F-score）／F1スコア（F1-score）
    - 重み付きF値（Weighted F-measure）／Fβスコア（Fβ-score）
    - LogLoss（Binary Logarithmic Loss）
    - AUC（Area Under the ROC curve、ROC曲線のAUC）
    - PR-AUC（Area Under the Precision-Recall curve、AUC-PR）／AP（Average Precision）
    
    **多クラス分類問題**
    - 正解率（Multi-class Accuracy）
    - LogLoss（Multi-class Logarthimic Loss）

 <br><br>
>  参考サイト
> 
> https://atmarkit.itmedia.co.jp/ait/articles/2104/15/news030.html<br>
> https://amateur-engineer-blog.com/machine-learning-metrics/
> https://atmarkit.itmedia.co.jp/ait/articles/2104/22/news022.html
ReLU関数について

# ReLU関数について
- **ReLU関数（Rectified Linear Unit function）**
<br>
<div style="text-align: center;">
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259691/db4cb6dc-dda5-8b10-39f3-c5124483c4c2.png" width="60%">
    <img src="/attachment/6268ec22ece6fa80e19dbcdb" width="60%">


     
図1:ReLU関数のグラフ
    
   出典：[https://atmarkit.itmedia.co.jp/ait/articles/2003/11/news016.html]
</div><br>

- 関数への入力値が0以下の場合には出力値が常に0、入力値が0より上の場合には出力値が入力値と同じ値となる関数である
- シグモイド関数は「-1」〜「1」しか出力を行わないが、ReLU関数は上限がない関数なので、その分学習の速度が早くなる、また計算式がシンプルであるのも早くなる理由である
- 座標点(0, 0)を基点として、ランプ型曲線のグラフになるため、ランプ関数（ramp function）とも呼ばれる
- ReLU関数は活性化関数の中でも隠れ層で非常に利用されている関数である
- 微分係数の最大値が1.0であるので、勾配消失問題を解消できる
- 0以下は常に0となるので、ニューロン群の活性化が疎になり、発火しないニューロン（＝生体ニューロンに近い動作）も表現できることで精度が向上しやすい


 <br><br>
>  参考サイト
> 
> https://atmarkit.itmedia.co.jp/ait/articles/2003/11/news016.html
分類問題でのSoftmax関数の役割

# 分類問題でのSoftmax関数の役割
- **softmax関数（Softmax function）**
    -  複数の出力値の合計が1.0（＝100％）になるように変換して出力する関数である
    -  各出力値の範囲は0.0～1.0となる
    -  滑らかな（＝ソフトな）曲線となり、1つの出力値が最大となるため「ソフトマックス関数」と呼ばれる
    -  分類問題に活性化関数として用いる場合、損失関数には（基本的に）交差エントロピーが用いられる
    
-  **分類問題でのsoftmax関数の役割**
<div style="text-align: center;">
    <img src="/attachment/6268d922ece6fa80e19d600" width="60%">
     
図1:softmax関数のグラフ
    
   出典：[https://atmarkit.itmedia.co.jp/ait/articles/2004/08/news016.html]
</div>
ソフトマックス関数の出力は0~1の実数値に落とし込むことができるため、出力値を確率として解釈することができる。（0.1なら10%、0.25なら25%のように）

上図は「虎（Tiger）＝緑色の線」に1.0、「ライオン（Lion）＝赤色の線」に0.0という固定値を入力し、「猫（Cat）＝オレンジ色の線」をX軸に取り-6.0～6.0で変化させたときのグラフである。<br>
X軸上のどこを取っても、3つの値の合計は1.0（つまり100％）となる。

分類問題の出力層でSoftmax関数を用いることで、入力データが、どのクラスに分類できるかの確率を算出することができる。
 <br><br>
>  参考サイト
> 
> https://atmarkit.itmedia.co.jp/ait/articles/2006/08/news031.html
AlexNet, ResNet, EfficientNetについて

# AlexNet, ResNet, EfficientNetについて
- **AlexNet**

    - 古典的な画像認識アプローチであるSIFT + Fisher Vector + SVMに大差をつけてILSVRC2012で優勝した、ディープラーニングの火付け役となったモデルとなります。
    - 構造がシンプルなため、他のネットワークのベースとして使用されることも多いモデル
    - 畳み込み層が5層で、そのうちのいくつかにはMaxPooling層がある
    - 出力層にはソフトマックス関数を持つ全結合層3層が使用されており、合計で8層により構成されている
    - ReLU関数・Dropout・データ拡張を採用し、精度向上している

<div style="text-align: center;">
    <img src="/attachment/626958a9ece6fa80e19f1dd" width="60%">
    
</div>

- **ResNet**

    - ILSVRC2015の優勝モデルで152層で構成されるCNN
    - 勾配消失問題や劣化問題によって学習が進まない問題を、Residual blockという手法を使って解決し、152層という非常に深い層を実現した表現力の高いネットワーク
<div style="text-align: center;">
    <img src="/attachment/62695a5fece6fa80e19f1ecf" width="60%">
    
</div>

-  大きな特徴としては、Residual Block(Shortcut Connectionを利用した残差ブロック)・Batch Normalization(バッチ正規化)が挙げられる。
    - Shortcut Connection<br>
    通常、入力xに対しての畳み込みを行って出力される関数H(x)を学習していくが、層が深いと差がなくなってくる。<br>この入力との差を、残差関数：Fx = Hx − xと 置き、このFx を学習対象とする考え方
    <br> 劣化問題 (勾配消失問題は起こっていないにも関わらず、層を深くした際に精度が劣化してしまう問題）を改善するための手法
    - Residual block
    <br>
    Shortcut connectionを使用し、層の入力を参照した残差関数を学習することで深いネッ トワークの学習を進みやすくする手法

- **EfficientNet**
<div style="text-align: center;">
    <img src="/attachment/62696647ece6fa80e19f24ea" width="80%">

</div>


2019年5月にGoogle Brainから発表されたモデルで、従来よりかなり少ないパラメータ数で高い精度を叩き出したState-of-The-Artなモデルである。<br>


モデルの「深さ」と「広さ」と「解像度(=入力画像の大きさ)」の3つをバランスよく調整している。
<br>

ConvNetsにおけるネットワークの深さや広さ、解像度などがモデルの性能にどう影響を及ぼすかを調べ、Compound Coefficient(複合係数) というものを導入することで性能を上げたところ、ImageNetを含む5つのデータセットで最高レベルを叩き出した


モデルが複雑ではなく、転移学習にも最適である


>  参考サイト
><br> https://qiita.com/omiita/items/83643f78baabfa210ab1utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items
DeepLearningと古典的なモデルの違い

# DeepLearningと古典的なモデルの違い

- 従来の機械学習では、画像からマニュアルで特徴量を抽出することからスタートし、抽出した特徴量を使って画像内の物体を分類するモデルを作成する
- ディープラーニングでは、特徴量は画像から自動的に抽出される
- ディープラーニングはエンドツーエンドな学習を実行でき、ネットワークは生の画像データと、分類など処理すべきタスクを与えられ、自動的にその処理方法を学習していく
- 機械学習のシャローラーニングと呼ばれる学習手法が、データ量が増加すれば性能に限界を迎えることに対して、ディープラーニングは読み込むデータの量が増えていくにつれ、その認識精度を向上していく
- 機械学習には幅広い手法、モデルがあり、用途や処理するデータサイズ、解決したい課題のタイプに合わせて選択することができるが、ディープラーニングを使用するには、データを高速で処理するための高性能なGPUだけでなく、モデルを学習させるために数千もの大量のデータが必要となる

![deepvsmachine.svg](/attachment/62690025ece6fa80e19e5b9)
図1:
機械学習(左)とディープラーニング(右)のアプローチの比較<br>
出典[https://jp.mathworks.com/discovery/deep-learning.html]
 <br><br>
>  参考サイト
> 
>https://jp.mathworks.com/discovery/deep-learning.html
deeplearningについて調査内容まとめ

以下について調査
- [DeepLearningと古典的なモデルの違い](/user/issei.fukuhara/kensyu/task1/DeepL)
- [AlexNet, ResNet, EfficientNetについて](/user/issei.fukuhara/kensyu/task1/cnnmodel)
- [分類問題でのSoftmax関数の役割](/user/issei.fukuhara/kensyu/task1/softmax)
- [Relu関数について](/user/issei.fukuhara/kensyu/task1/ReLU)
- [学習時の損失,評価関数の役割](/user/issei.fukuhara/kensyu/task1/Loss)
- [Validation(評価データ)の分け方について](/user/issei.fukuhara/kensyu/task1/splitval)
- [HyperParameter(ハイパーパラメータ)と学習結果の違い](/user/issei.fukuhara/kensyu/task1/hyperpara)
- [Optimizer(最適化)の種類について](/user/issei.fukuhara/kensyu/task1/Optimizer)
- [ Batch normalization(バッチ正規化)の役割](/user/issei.fukuhara/kensyu/task1/batch-normalization)
- [Dropout(ドロップアウト)の役割](/user/issei.fukuhara/kensyu/task1/dropout)
- [Auto Encoder(オートエンコーダー)について](/user/issei.fukuhara/kensyu/task1/AutoEncoder)
- [BatchNormalizationとDropoutの併用について](/user/issei.fukuhara/kensyu/task1/batch-drop)
Google Chromeの閲覧履歴を手動で削除する




```

Shift]＋[Ctrl]＋[Delete]



Google Chromeの閲覧履歴を手動で削除するには以下の手順で行います。

Google Chrome（グーグル・クローム）を起動し、最前面に表示している状態でキーボードの[Shift]＋[Ctrl]＋[Delete]を押す

[閲覧履歴データの削除]と書かれた画面が表示されるので、削除する期間等を選択し、[データを削除]をクリック
Unity Catalogの権限継承へのアップグレード

[Upgrade to privilege inheritance \| Databricks on AWS](https://docs.databricks.com/data-governance/unity-catalog/manage-privileges/upgrade-privilege-model.html) [2022/10/3時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

パブリックプレビューの期間中(2022/8/25以前)にUnity Catalogメタストアを作成している場合には、権限継承を利用できる様にするために、権限モデルバージョン1.0をアップグレードすることができます。権限モデルをアップグレードするまでは、既存のワークロードはそのままで動作し続けます。権限継承や新機能を活用できる様にするために、権限モデルバージョン1.0にアップグレードすることをお勧めします。

# 権限モデルバージョン1.0における変更点

Unity Catalogにおける権限モデルv1.0は、パブリックプレビューの権限モデルとは以下の点で違いがあります。

- **権限継承:** 権限モデルv1.0では、権限は子供のセキュリティ保護可能オブジェクトに継承されます。これは、カタログで権限を付与すると、自動でカタログ内の現在、将来のオブジェクトに権限が付与されることを意味します。同様に、スキーマに付与された権限は、スキーマに存在する、あるいは、今後作成さくせいされるすべてのオブジェクトに継承されます。プレビューのモデルでは、子供のセキュリティ保護可能オブジェクトに権限は継承されませんでした。権限継承の詳細に関しては、[継承モデル](https://docs.databricks.com/data-governance/unity-catalog/manage-privileges/privileges.html#inheritance)をご覧ください。
- **`ALL PRIVILEGES`の評価方法が変わります:** パブリックプレビューの顕現モデルでは、`ALL PRIVILEGES`は権限を付与した時点で利用可能なすべての権限をプリンシパルに許可していました。権限モデルv1.0では、`ALL PRIVILEGES`権限は、権限チェックが行われた際に利用可能なすべての権限に拡張されます。
- **`CREATE TABLE`は`CREATE EXTERNAL TABLE`にアップデートされます:** `CREATE TABLE`権限は今後は、外部テーブルの作成に必要な外部ロケーションやストレージ認証情報には適用されません。権限モデルv1.0では、代わりに外部ロケーションやストレージ認証情報に対して、ユーザーが外部ロケーションやストレージ認証情報を使用して外部テーブルの作成を許可するには`CREATE EXTERNAL TABLE`を許可します。
- **`CREATE`は削除されます:** `CREATE`権限は削除され、以下のより詳細な権限で置き換えられます：`CREATE CATALOG`、`CREATE EXTERNAL LOCATION`、`CREATE FUNCTION`、`CREATE SCHEMA`、`CREATE TABLE`、`CREATE VIEW`。
- **`USAGE`は削除されます:** `USAGE`権限は削除され、以下のより詳細な権限で置き換えられます：`USE CATALOG`、`USE SCHEMA`。

# 権限モデルバージョン1.0へのアップグレード

:::note alert
**警告！**
このアクションを取り消すことはできません。
:::

1. [Databricks Runtime 11\.1](https://docs.databricks.com/release-notes/runtime/11.1.html)以降を使用するために、Unity Catalogを参照するすべてのワークロードをアップグレードします。

    すべてのクラスターでDatabricksランタイム11.1以降を使用する様にアップグレードし、実行中のすべてのSQLウェアハウスを再起動する必要があります。このステップをスキップすると、古いバージョンのDatabricksランタイムで動作するワークロードは、アップグレード完了後にアクセスが拒否されます。

1. アカウント管理者として[アカウントコンソール](https://accounts.cloud.databricks.com/)にログインします。
1. ![](https://docs.databricks.com/_images/data-icon.png)**Data**をクリックします。
1. メタストア名をクリックします。
1. **Privilege Model**の下の**Upgrade**をクリックします。
1. **Upgrade**をくりっっくします。

アップグレードのオプションが表示されていない場合、お使いのUnity Catalogメタストアはすでに権限モデルv1.0を使用しています。

# アップグレードSQLコマンド(オプション)

Databricksでは、古い権限モデルを用いて表現されるgrantをサポートし続け、権限モデルv1.0の同等のgrantに自動でマッピングします。しかし、`SHOW GRANTS`や`information_schema`のデータは、権限モデルv1.0を参照し続けます。既存のコードがアップデートされた権限モデルを参照してgrantを実行する様にアップグレードすることをお勧めします。

- 外部ロケーションやストレージ認証情報に対する`CREATE TABLE`権限を`CREATE EXTERNAL TABLE`権限で置き換えてください。
- `CREATE`権限をより固有な権限で置き換えてください：`CREATE CATALOG`、`CREATE EXTERNAL LOCATION`、`CREATE FUNCTION`、`CREATE SCHEMA`、`CREATE TABLE`、`CREATE VIEW`。
- `USAGE`権限をより固有な権限で置き換えてください：`USE CATALOG`、`USE SCHEMA`。

Unity Catalogの権限モデルの詳細に関しては、[Unity Catalog privileges and securable objects](https://docs.databricks.com/data-governance/unity-catalog/manage-privileges/privileges.html)をご覧ください。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Rails7 + TailwindCSS + daisyUIの導入で詰まった時の解決手段

## 概要
`Rails7` + `TailwindCSS` の構成でアプリケーションを作成し、 `daisyUI` を導入したが表示がうまくいかずに詰まった。


## 結論
**npm** で `daisyUI` をインストールして使用する。


## 環境
`Rails7` でアプリケーション作成時に `TailswindCSS` を以下のようにして導入
```bash
$ rails new MY_APP --css tailwind
```
　以上のようにアプリ作成を行うと、Gemfileに `gem tailwindcss-rails` が追加され、このgemによって導入される。


## daisyUIの導入
失敗したケースと成功したケース、未検証のケースをそれぞれ記載する。


### 失敗ケース(CDNによる導入)
#### 方法
`application.html.erb`のheader部分に [公式サイト](https://daisyui.com/docs/cdn/)のリンクを追記する。

```erb:application.html.erb
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
<link href="https://cdn.jsdelivr.net/npm/daisyui@2.24.0/dist/full.css" rel="stylesheet" type="text/css" />
```

#### 起きた問題
`tailwindcss`で定義されている一部のクラスで色が表示されないなどの問題が起きた。
読み込み順を変更した場合も、同様の事象が起きる。

#### 原因
`daisyUI`の**CDN**で提供されるスタイルシート内に**リセットcss**も含まれていることが原因。
gemで追加した`tailwindcss`が`daisyUI`の不要なクラスを削除できないことが**問題**。


### 失敗ケース（importmapによる導入）
**importmap** を利用して、プラグインとして`daisyUI`を導入しようとした。

#### 方法
ターミナルで以下のコマンドを実行する。
`config/importmap.rb` に自動で`daisyUI`を利用するために必要なものが追記される。
```bash:ターミナル
$ rails importmap:install daisyui
```

`config/tailwind.config.js` に以下の内容を記述。
```js:config/tailwind.config.js
module.exports = { plugins: [require("daisyui")] }
```

#### 起きた問題
daisyUIが反映されない。

#### 原因
railsにtailwindcssを導入するために使用している、 gem `tailwindcss-rails` が importmapを使用した **plugins** に対応していない。


### 成功ケース(npmによる導入)
#### 方法
**npm** によってdaisyUIを導入した。
```bash
$ npm i daisyui
```

`config/tailwind.config.js` に以下の内容を記述。
```js:config/tailwind.config.js
module.exports = { plugins: [require("daisyui")] }
```

#### 結果
表示の不具合が起きなくなった。


### 未検証ケース(tailwindcssの導入方法を変更)
今までのケースは`tailwindcss`をgem　の `tailwindcss-rails` を使用して導入することを前提としているが、gem `cssbundling-rails` で導入した場合は **importmap**による `daisyUI`　の導入ができるかもしれない。

## おわりに
記事内の問題点や、未検証ケースを試していただいた場合はコメントにてお知らせいただけると嬉しいです。
【shopify】gidで商品情報を取得する

gidで商品情報取るのに苦戦しまくったので記録しておきます。

## メタフィールドで取ってこれる商品の情報がgidだけってマジ？
shopifyにはメタフィールドという、WPやMTでいうところのカスタムフィールドがあります。
ページやブログ記事、商品などに任意の項目を追加することができるので便利です。

[メタフィールド · Shopify ヘルプセンター](https://help.shopify.com/ja/manual/metafields)
[【Shopify】メタフィールドについて - Qiita](https://qiita.com/eijiSaito/items/ebe3465c345cafba1b42)

今回私はブログ記事に関連商品という項目が作りたかったので、ブログ記事に対して商品を１つ紐付けられるメタフィールドを作成しました。
メタフィールドで設定した値は、liquid内で `article.metafields.custom.hoge` という感じで使うことができます。

メタフィールドで商品を選択すると、取得できる情報はgidというものになります。
`gid://shopify/Product/1`　みたいな感じです。

全商品から特定の商品を検索したい場合は `all_products["ハンドル名"]` で取得できます。
だがハンドル名てよぉ・・こちとらgidしかないねん・・
となって現在に至ります。

## gidをもにゃもにゃして商品情報を取ってくる
### 前提
- ブログ記事に_productという名前でメタフィールドを作成しました
👉 `article.metafields.custom._product`
- 全商品が登録されているコレクションがあります（ハンドルは`all`）

### 処理
```liquid:article-template.liquid
{% assign split_id = article.metafields.custom._product | split: "/" %}
{% assign the_id = split_id | last %}
{% assign product_id = the_id | times: 1 %}
{% assign products_obj = collections.all.products | where: 'id', product_id %}
{% assign related_product = products_obj[0] %}

<h2>関連商品</h2>
<p>商品タイトル: {{ related_product.title }}
<p>価格: {{ related_product.price | money }}</p>
<p>商品画像: 
{% for image in related_product.images limit:1 %}
  <img src="{{ image.src | product_img_url: 'medium' }}">
{% endfor %}
</p>
```

1. gidを`/`で区切った配列にする
1. 最後の要素=商品IDを取得する
1. すべての商品が登録されているコレクションから、IDで商品検索をする
1. 目的の商品オブジェクトゲットだぜ

という流れになります。

この方に大感謝です👇
[How to get product Information by Product ID ? - Shopify Community](https://community.shopify.com/c/shopify-apps/how-to-get-product-information-by-product-id/td-p/1604231)

自分が調べてみた限りでは、handleで指定するやり方ばかり出てきまして
ID～～～～～！！！！と数時間暴れてこうなりました。
一撃で取れる方法あったら、めっちゃ悔しいんですけど教えてください。

乙！！

## 参考
[メタフィールド · Shopify ヘルプセンター](https://help.shopify.com/ja/manual/metafields)
[【Shopify】メタフィールドについて - Qiita](https://qiita.com/eijiSaito/items/ebe3465c345cafba1b42)
[How to get product Information by Product ID ? - Shopify Community](https://community.shopify.com/c/shopify-apps/how-to-get-product-information-by-product-id/td-p/1604231)
[iquid objects: product](https://shopify.dev/api/liquid/objects/product)
【データ基盤構築/BigQuery】URLの表記揺れの名寄せを行う

# 今回の課題
社内のマスタデータからBigQueryにデータを取り込んだところ、URLに表記揺れがあった。
処理をしやすいように名寄せ処理を行う必要があった。

# 名寄せ処理が必要なデータを目視で探した
下記のクエリを実行して、データの除去や名寄せが必要なデータを目視でざっと探してみた。
```SQL
--dateをdate型に変換。page_pathが「/contents/」で始まるURLに絞る。page_pathの「index」「&」「?」文字列以降のデータを削除。
with master as (
    select
        page_title
        , page_path
    from
        `テーブル名`
    where
        regexp_contains(page_path, r'^/contents/') --「/contents/」で始まるURLに絞る。   
)

--page_pathカラムがすべて「/」で終了するように調整。
, master2 as (
    select
        page_title
        , split(page_path, '/') as page_path_array
    from
        master
)

--必要なカラムを抽出
select 
    page_path_array
    , offset
from 
    master2 as m
cross join unnest(m.page_path_array)　as page_path_array
with offset as offset
group by
    page_path_array 
    , offset
```
### 上記クエリの解説
* CROSS JOIN UNNESTとSPLIT関数を組み合わせることで、URLを単一の列の複数レコードに分割している。
※参考：[cross join unnestを利用して、カンマ区切りのデータを単一の列の複数レコードに分解する](https://qiita.com/shohei727/items/80aebf3956d48fb509a6)
* `page_path_array`, `offset`でGROUP BYすることによって、ユニークなデータを抽出している。こうすることによって、目視で探すデータの数を減らした。
* `with ofset as offset`で添え字をoffsetカラムに格納するようにしている。
※参考：[BigQueryのArrayを理解する](https://zenn.dev/a1008u/articles/acbd17961f7f5d95a2a8)



上記のクエリを実行した結果、下記の`名寄せ処理の条件`の項目のURLを名寄せする必要があると分かった。
## 名寄せ処理の条件
下記のように名寄せを行った。
1. `/contents/`から始まるURLに絞り込む（それ以外は除外する）
2. `index`が付いているURLを除外（URLの最後に`index.html`といった記述があるものを除外したい。）
3. パラメータ付きのURLを除外（`?~`, `&~`となっているURL）
4. `/`で終わっていないURLは、`/`を付け足しする。
5. 上記を除外した後で他に最後のスラッシュ後に余計なものが付与されているデータを除去する。（offsetが`4`なのに、`https://～`という文字列が付いているURLがあったので、それを除去したい。）

※除外しきれないURLがあった際、そういったデータはゴミデータとして除外してしまうのもあり。


## 実装方法
* 名寄せ処理の条件1~4について
`page_path`の`index`, `&`, `?`文字列以降のデータを削除した状態から、
更に`/`で終っているかどうかを正規表現で判定して`/`で終わっていなければ`/`を末尾に付与する。

* 名寄せ処理の条件5について
1~4を除外した後に、最後の`/`の後ろに`https:~`が付与されていたので、
下記クエリの`(.*/https:/).*$`で除外した。

```SQL
with master as (
    select
        page_title
       , regexp_replace(normalize(page_path, NFKC), r'(index|&|\?).*|[^a-zA-Z0-9-/:-@-~_]|[ +]|(.*/https:).*$', "") as page_path_fix --データの揺れを調整
    from
        `テーブル名`
    where
        regexp_contains(page_path, r'^/contents/') --「/contents/」で始まるURLに絞り込む。
)

select
    page_title
    , page_path -- 一応、元のpage_pathも保持しておく
    , if(regexp_contains(page_path, r'.*/$'), concat(page_path, ""), concat(page_path, "/")) as page_path_fix -- page_pathカラムが全て「/」で終了するように調整。
from
    master
;
```
### 補足
* 全角数字が混在していたので、`normalize(page_path, NFKC)`で正規化（英数カナすべて統一）した。
NFKC正規化は、「全角を半角にする」時に役に立つ。（参考：[全角英数字を半角に変換【BigQuery】](https://qiita.com/yyyyy__78/items/3c40a5a6d64af466f5a7)）
 
* 業務では上記クエリの正規表現で、URLを名寄せできたが、こちらの引用URLの正規表現も使えそう。（引用の方が良さそうなので試してみる）
※参考：[【BigQuery】正規表現を使ってURLを分解する - ドメイン名｜パス(path)｜utmパラメータ
](https://qiita.com/sushi_edo/items/a7a275c7059f99962b69)

* `page_path_fix`（名寄せしたURL）と`page_path`（名寄せする前のURL）は、
念のため両方保持しておくのが良さそう。（確実に不要であれば、除去してもOK)

以上で、名寄せ処理が完了した。
【shell】【online-judge-tools】競技プログラミングの鉄則　演習問題集のサンプルケースを自動で取得する



# Introduction
online-judge-toolsを使って、サンプルケースをテストしています。競技プログラミングの鉄則を購入し、atcoder上のサンプル問題を使って黙々と説いています。


しかし、毎回リンクをコピペして、下記のコマンドを実行するのはめんどくさいな・・・と感じるようになりました

```bash:bash
mkdir ファイル名
oj d link先をコピペ
```


それなら、シェルでwebスクレイピングして、自動で作ったろ！！と思い立ち、作成しました。

本当はcurlを変数に代入して、それに対してgrepしたかったのですが、思うような結果が得られなかったので、一度grepした結果をtxtに出力しています。その後テキストファイルを読み込んで、ループを回してます。

## 前提条件
online-judge-toolsの設定が済んでいること

```bash

oj login --check "https://atcoder.jp/"
```
```bash

[SUCCESS] You have already signed in
```
と表示されていれば、多分通ると思います。

## 今回使用したversion
Ubuntu 22.04 LTS
online-judge-tools 11.5.1
GNU bash, バージョン 5.1.16(1)-release (x86_64-pc-linux-gnu)


# 作ったスクリプト

```bash:a.sh
#競技プログラミングの鉄則URLを取得
URL=https://atcoder.jp/contests/tessoku-book/tasks

curl -fsSL ${URL} | 
grep -oP '(?<=<td class="text-center no-break"><a href=").*(?=">)' >title.txt

curl -fsSL ${URL} |
grep -oP '(?<=<td class="text-center no-break"><a href=").*(?=/a>)'|
grep -oP '(?<=">).*(?=<)'>list.txt




# 区切り文字を改行コードに指定
IFS=$'\n'
 
# ファイルを配列に読み込む
file=(`cat title.txt`)
name=(`cat list.txt`)


# 行ごとに繰り返し処理を実行
for((i=0; i<${#file[@]}; i++))
do
    mkdir ${name[i]}
    cd ${name[i]}
    oj d "https://atcoder.jp"${file[i]}
    cd ..

done

rm title.txt
rm list.txt
```







## 実行後
```
test/
├── A01
│   └── test
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       ├── sample-2.out
│       ├── sample-3.in
│       └── sample-3.out


・・・長いので省略

├── C20
│   └── test
│       ├── sample-1.in
│       └── sample-1.out
└── a.sh

```


# 参考サイト
https://atcoder.jp/contests/tessoku-book

https://github.com/online-judge-tools/oj/blob/master/docs/getting-started.ja.md
Cognitoとnuxtでメールの２段階認証を開発する方法

## 前提知識
- nuxt
- Cognito
## フロント側
以下をコマンドプロンプトなどに入力し、amplifyのライブラリをインストールする。(引用サイト：amplifyAPI)
```console
$ npm install aws-amplify @aws-amplify/ui-components
```


amplifyのAPIを使用し、Cognitoへユーザー名やパスワードなど必要な情報を送信する。
```diff_javascript
import { Auth } from 'aws-amplify';

async function signIn() {
    try {
        await Auth.signIn(username, password);
    } catch (error) {
        console.log('error signing in', error);
    }
}
```
2段階認証では、1段階目の認証で作成したuserとバックエンド側で作成した認証コードを送信する。
```diff_javascript
import { Auth } from 'aws-amplify';

async function challenge() {
    try {
        await Auth.sendCustomChallengeAnswer(user, challengeResponses);
    } catch (error) {
        console.log('error signing in', error);
    }
}
```
`.env`ファイルに以下のようにユーザープールIDなどを設定する。
```env
COGNITO_USER_POOL_ID = 'xxxxxxxxx_xxxxxxxx'
COGNITO_CLIENT_ID = 'xxxxxxx...'
REGION='xxxxxxxxx'
```

## Cognito設定
* カスタム属性に「auth_challenge」を追加
* カスタム認証を利用するため、MFAはオフに設定
* アプリクライアントを設定
    - 認証フローの設定に全てチェック
    - セキュリティ設定は有効(推奨)
    - トークンを取り消しを有効化にチェック
* 他は全てデフォルトで設定
## バックエンド側
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746038/6d3d3cba-6458-d3d6-90a7-cbfea30b8767.png)
上画像のようなフローでカスタム認証を行います。

引用サイト（Amazon Cognito MFA with Email Using Lambda Triggers(以後Cognito MFA)）の1～3つ目のプログラムをLambdaに登録し、上からCognitoの「認証チャレンジの定義」、「認証チャレンジの作成」、「認証チャレンジの確認」に設定します。

Cognito MFAのプログラムには認証コードを作成する処理がないため処理を追加する必要があります。

## 引用サイト
* [Amazon Cognito MFA with Email Using Lambda Triggers](https://jamesingold.com/amazon-cognito-mfa-with-email-lambda-triggers#:~:text=Amazon%20Cognito%20is%20a%20great,as%20Authy%20or%20Google%20Authenticator)

* [amplifyAPI](https://docs.amplify.aws/lib/auth/emailpassword/q/platform/js/)

* [AWSCognitoカスタム認証フロー](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-lambda-challenge.html)

* [カスタム認証チャレンジの Lambda トリガー](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html)
フロントエンドコーディングでやっておきたいこと

:::note warn
掲載内容が多くなったため記事を分けて再公開しました。
:::

https://qiita.com/taqumo/items/3660b04400c28c5c2aa5

https://qiita.com/taqumo/items/0c7116517bb2b44b2939

https://qiita.com/taqumo/items/d69522e2f3b95bf02996

https://qiita.com/taqumo/items/76a47a588b896e3c9840
【UiPath】物体検出モデルの出力結果に座標を出したい（AI Center）

# はじめに
以前、物体検出モデル（オープンソースモデル）を検証しました。

https://qiita.com/shuy/items/c92affc3d7b2433dba89

このモデルの出力は以下の通り、クラス（class）と確信度（score）を返すだけとなり、座標値を取得することはできません。

```
{
  "Predicted Class ": "[
    {'class': 'package', 'score': ' 0.93'}
  ]",
  "Predicted ByteArray": "..."
}
```

しかし、業務でモデルを利用する場合、検出したオブジェクトの座標を知る必要があるケース（特定の場所に特定のオブジェクトが検出されるかをチェックするなど）も多いので、このモデルをカスタマイズして、座標を取れるようにしてみます。


# つかうもの
※クラウド環境は2022年11月時点のもの
* Automation Cloud(AI Center) Enterprise版

# パッケージをダウンロードする
まずは、MLパッケージをダウンロードします。
![ダウンロード1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/2e0a7727-31f2-ea96-9e2b-5be6d96e8a60.png)

メタデータ（JSONファイル）とソースコード（ZIPファイル）をダウンロードすることができます。
![ダウンロード2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/77636556-0de9-8da1-8e10-7dbb804997df.png)


# Pythonコードを修正する
今回、取得する座標は検出オブジェクトの左上と右下の2点となります。
![ソースコード2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/9c6a4eb8-5a08-167f-b5c4-a7fda26d420a.png)

ZIPファイルを展開し、適当なエディタでソースを開き、修正します。
修正対象は、yolov3\utils.py です。206行目（draw_bbox内）の下に4行コードを追加します。

``` utils.py > draw_bbox
dict["coordinate_x1"]=x1
dict["coordinate_y1"]=y1
dict["coordinate_x2"]=x2
dict["coordinate_y2"]=y2
```

![ソースコード1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/702871dc-b47c-6c8b-454e-a2f9baed0f3a.png)

ソースコードの修正が終わったら、再度ZIPファイルにまとめます。


# パッケージをアップロードする
「MLパッケージをインポート」から修正済みのソースコードをアップロードします。
紛らわしいのですが、「新しいバージョンをアップロード」ではありません。
![アップロード1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/942f1820-35b3-d894-433b-fb1abac04530.png)

ソースコード（ZIPファイル）とメタデータ（JSONファイル）をアップロードします。
メタデータはダウンロードしたファイルをそのまま使用するので、修正する必要はありません。
![アップロード2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/06f5d65f-5eca-f843-03af-894177d1d890.png)

アップロードは、そこそこ時間がかかるので、我慢して待ちましょう。
アップロードが完了すると、新しいバージョンのパッケージが一覧に追加されます。ステータスは「検証中」となっていますが、しばらくすると「未デプロイ」となり使用可能（パイプラインやデプロイ）な状態となります。
![アップロード3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/e00b03d8-0b60-322e-1190-16af782fc8d1.png)


# 実行結果
以下、犬が3匹写っている写真をインプットに物体検出をしてみます。
![dogs.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/1bdf9b37-6774-4301-afa0-c8826bc085d7.jpeg)

結果は以下の通りです。3つのオブジェクト（class=dog）が検出され、それぞれ座標も取ることができました。
![実行結果1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/752315bd-92da-88d1-3758-c4123043f69c.png)

取得できた座標を元のインプット画像にプロットしてみると、以下のようになります。
![実行結果2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89445/b78fa444-858d-6085-a73c-be2bb07defb5.jpeg)


# おわりに
以上のようにAI Centerで、すぐ使えるプリセットのモデルですが、Pythonコードを修正することでモデルのカスタマイズが可能です。
Pythonの知識とソースコードを解析するスキルは必要ですが、今回のような座標を出力するだけなら、すごい難しいものではありません。
プリセットのモデルが業務に適さない場合、すぐに諦めるのではなく、カスタマイズ可能かどうか確認してみても良いかもしれません。
ただし、より高度なカスタマイズをしたい場合は、機械学習の専門的な知識が必要となりますので、ハードルは一気に高くなると思うので注意が必要です。
技術的負債についての向き合い方

# これは何か?

- 技術的負債になりえそうなコードに出会ったときにどう対応するかについて書いてある

# 技術的負債とは？

- 今後の開発体験を悪化させたり、非機能要件的に問題があるソースコードのこと 

# 技術的負債に対するアプローチ

以下の順番で対応する

1. まずはとにかく可視化
1. 負債をグルーピング
1. 負債の影響範囲から優先順位づけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134704/dac166bb-08b2-9f66-d624-8f88b230acf3.png)

## PHASE1. まずはとにかく可視化

- チケットとしてはすでに報告されていたり、duplicatedになってしまったり、invalidになるかもしれないけど、とにかくカジュアルにリファクタリング用のチケットを起票する
- 負債解消を後回しにした場合、その該当するPRに対して、リファクタリングイシューから必ずリファレンスしておく（どこで具体的につらかったのか後で対応する人がわかるようにするため）
- ツールとかは別になんでもいいが、ミニマムでやるのであればGithub IssueやPull Requestレベルでまとめておくとよい。

## PHASE2. 負債をグルーピング・関連付け

- 関連する負債に関しては、PRやイシューに対してリファレンスをつける
- あえてそのPR内で対応しなかった理由があると、なぜそれが負債として残っているのかわかっているとよい。

## PHASE3. 負債の影響範囲から優先順位づけ

負債として、以下の観点で優先づけることが多い。

- 報告数の多いチケット -> 開発チーム全体での開発体験が損なわれているチケットの可能性が高い
- 最もリファレンスされているチケット -> 問題の根本要因の可能性が高い。

ここも、PHASE1を最初からやっておけば、優先順位づけがしやすくなる。


# 技術的負債を減らすうえで大事なこと

## ①とにかく、負債を可視化すること

問題点が可視化されていれば、対応することができるが、問題が認識できない状況であれば
そもそも対応ができない。

よって、負債の匂いを感じるコードを見つけたら、負債解消を先送りにするのであれば必ずイシューを起票し、リファクタリングタグをつけておくこと。いつ対応するかは一切考えなくてもよい。

後でチケットのリファレンス数や、同じ問題がどれくらい起票されるかで、つらみ度がわかる。
チケットの起票がないと、優先順位をつけづらいので、対応が後回しになる可能性が非常に高い。

## ②どんなに小さな問題でも、起票しておくこと。

意外にその時は「まあ起票するほどでもないか、」と思っても、後で優先順位つけておくときに実はすぐ対応する必要がある可能性がある。起票時は優先順位はいったんつけずに、とにかく可視化、可視化をしておくことが重要。どんなに小さな問題でも、起票しておくこと。

## ③PRのレビュー時、負債であることをレビュワーに認識してもらうこと

コードレビューを受ける際も、負債を残しておく意思決定をしているか明示的に書いてあれば、レビュワーがその技術的負債に対して、突っ込むべきかどうかの議論に時間をかけなくても済む。よって、レビューを受ける前に負債解消を後回しにしたことを明示的に記載しておくべき。
Azure Fundamentals(AZ-900)：Azure の基礎: Azure のアーキテクチャとサービスについて説明する「多層防御」

Microsoft Learnを用いたMicrosoft Azure Fundamentals(AZ-900)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始める方の参考になれば幸いです。

## 今回の学習内容
**◆「多層防御」**
◇対応するMicrosoft Learn ラーニングパス
[Azure の基礎: Azure のアーキテクチャとサービスについて説明する](https://learn.microsoft.com/ja-jp/training/paths/azure-fundamentals-describe-azure-architecture-services/)
◇対応するモジュール
[多層防御について説明する](https://learn.microsoft.com/ja-jp/training/modules/describe-azure-identity-access-security/8-describe-defense-depth)

※前回の投稿は下記から確認できます。
[Azure Fundamentals(AZ-900)：Azure の基礎: Azure のアーキテクチャとサービスについて説明する「ゼロトラストモデル」](https://qiita.com/fsd-jume/items/3a810aa99b01ac3e4731)

## 多層防御
**複数の層でそれぞれセキュリティ対策を実施し、データへの不正アクセスなどを防ぐ**
⇒1つの層が破られた場合も後続の層でセキュリティを確保
⇒単一の保護層への依存がなくなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/978234e2-0f75-a80e-2b2d-5d09401dd172.png)

###  物理的なセキュリティ層
・リソースへのアクセスに対する物理的な保護
例)データセンター内における生体認証

### IDとアクセス層
・IDのセキュリティ保護やアクセス制御、サインインや変更のログ保管
例)SSOと多要素認証を使用
例)インフラへのアクセスや変更を制御

### 境界層
・リソースに対するネットワークベースの攻撃を識別し、影響の排除、発生時の警告を行う
例)DDoS保護を使用して、ユーザのシステムに影響が出る前に攻撃をフィルター処理
例)境界FWを使用して、ネットワークに対する悪意ある攻撃を識別し警告
※DDoS：対象に大量のパケットを送ることで、通常のパケットを妨害する悪意ある行為

### ネットワーク層
・すべてのリソースに対するネットワーク接続を制限し、必要な接続のみを許可
・ネットワーク内の他システムに攻撃が拡散されるリスクが軽減
例)リソース間の通信を制限
例)必要に応じて、インターネットの受信アクセスを限定し、送信アクセスを制限
例)オンプレミスネットワークへのセキュリティで保護された接続を実装

### コンピュータ層
・コンピューティングリソースをセキュリティで保護
・セキュリティ上の問題を最小限に抑えるための管理を適切に実行
例)VMへのアクセスをセキュリティで保護
例)デバイス上にエンドポイント保護を実装し、システムに修正プログラムを適用して最新の状態に保つ

### アプリケーション層
・アプリをセキュリティで保護
・アプリからセキュリティ上の脆弱性をなくす
例)機密性の高い認証情報をセキュリティで保護されたストレージに格納
例)セキュリティをすべてのアプリ開発の設計要件にする

### データ層
・保護する必要があるビジネスと顧客のデータへのアクセスを制御
・データにおける機密性、整合性、可用性の管理
・攻撃者により狙われるデータの例
　-データベースに格納されたデータ
　-VM内のディスク上に格納されたデータ
　-Office 365などのSaaSアプリに格納されたデータ
　-クラウドストレージを介して管理されているデータ

## 次の学習内容
**◆Microsoft Defender for Cloud**

https://qiita.com/fsd-jume/items/c5d2d1e60912b0c698d8

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8
YDLIDAR GS2をPythonから使う

# YDLIDAR GS2
- YDLIDAR GS2は可動部がない2Dlidar。
- 6000円ぐらい
-
## プロトコル
- https://www.ydlidar.com/Public/upload/files/2022-10-18/YDLIDAR%20GS2%20Development%20Manual%20V1.6.1(220602).pdf

## teratermから使ってみよう

teratermのマクロを利用してバイナリでコマンドを送る
[teraterm バイナリでデータを送受信するやり方](https://eng-memo.info/blog/teraterm/)
```terminal
send $A5$A5$A5$A5$00$63$00$00$63
```
こんな感じでデータがかえってくる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528717/ca24bdb3-5572-3079-c346-b4177aeddad3.png)

データ形式はこんな感じになってるらしい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528717/9867329d-ad48-6151-5ecb-1409a0e9e65e.png)

Data segment部が環境データが1バイト、距離、強度のデータがが160ポイント分320バイトあるらしい
2byteなので16bit
上位7bitは強度,下位9bitは距離のデータらしい
<input type=date /> とReact Hook Formで日付のデフォルト値が表示されない時の対処法

## これはなに？

Chakra UIのDatePicker（`<Input type="date" >`）をReact Hook Formで使った時にデフォルト値が表示されなくて困ったので記事に残しました。

この記事が同様の問題で悩んでいる人の助けになれば嬉しいです。

## この記事のゴール

以下の理解を得ることをゴールとします

- Chakra UIの`<Input type="date"/>`のデフォルト値を表示する方法が分かること

## 環境

| ツール・ライブラリ | 用途 | バージョン |
| --- | --- | --- |
| React | フロントエンドのFW | 18.2.0 |
| Chakra UI | UIライブラリ | 2.3.6 |
| React Hook Form | フォームバリデーションツール | 7.38.0 |
| yup | バリデーションのためのスキーマビルダー | 0.32.11 |

## 課題

誕生日を入力するフォームにデフォルトに値を今日の日付を設定したいとします。

そうするとコードは以下のようになります。

```tsx
import {
  Container,
  FormControl,
  FormErrorMessage,
  FormLabel,
  Heading,
  Input,
} from '@chakra-ui/react'
import { yupResolver } from '@hookform/resolvers/yup'
import { useForm } from 'react-hook-form'
import * as yup from 'yup'
import type { NextPage } from 'next'

const Sample: NextPage = () => {
  const validations = yup.object().shape({
    birthDate: yup.date().required('誕生日を入力してください'),
  })

  const defaultBirthDate = new Date() //デフォルト値を設定

  const {
    register,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(validations),
    defaultValues: {
      birthDate: defaultBirthDate,
    },
  })

  const birthDateErrorMessage = errors
    ? (errors['birthDate']?.message as string)
    : undefined

  return (
    <>
      <Container py={8} px={4}>
        <Heading>ダメな例</Heading>
        <form>
          <FormControl>
            <FormLabel mt={4}>生年月日</FormLabel>
            {birthDateErrorMessage && (
              <FormErrorMessage>{birthDateErrorMessage}</FormErrorMessage>
            )}
            <Input {...register('birthDate')} type={'date'} />
          </FormControl>
        </form>
      </Container>
    </>
  )
}

export default Sample
```

が、ローカルで起動してみると以下の画像のように`defaultBirthDate`で設定したデフォルト値が表示されません。

![damena_rei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/b1435159-8e77-b1a4-c347-811607693eb4.png)


## 解決方法

Chromeのコンソールを見てみると以下のような警告が表示されていました。

> The specified value "Sat Oct 29 2022 20:23:53 GMT+0900 (\u65E5\u672C\u6A19\u6E96\u6642)" does not conform to the required format, "yyyy-MM-dd".
> 

つまりDate型をbirthDateのdefaultValueに渡すのではなく、`yyyy-MM-dd`で渡すことで表示されるとのことでした。

```tsx
~~~ 省略 ~~~

const defaultBirthDate = new Date()
  const formattedDefaultBirthDate = format(defaultBirthDate, 'yyyy-MM-dd', {
    locale: ja,
  }) //デフォルト値を設定

~~~ 省略 ~~~
```

実際に`yyyy-MM-dd`のフォーマットで渡してあげると正常に表示されるようになりました。

今回はdate-fnsでフォーマットの変更をするようにしました。

![yoi_rei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/da707cd4-2e32-bf45-b1ca-e43bc3bac5b3.png)


## 余談

Date型だからブラウザ側でよしなに表示してくれると思いきや、思わぬトラップでした。

色々とググってみるとinputのdateの時はyyyy-MM-ddにしなさいという旨の記事にもありました。

先人の知恵に感謝ですね。

https://qiita.com/day-1/items/5091a382f82564a27bc6

ではまた！
Next.jsでパスに \ud が含まれるとサーバー起動できないエラー


僕が提供している[Next.jsのコース](https://www.takux.one/#notion-next-blog)の中では、はじめのほうで `create-next-app` でセットアップした後、 `yarn dev` でサーバーを立ち上げて表示を確認しています。

すると、下記のようなエラーが発生した方がいました。

```
$ yarn dev
...
ready - started server on 0.0.0.0:3000, url: <http://localhost:3000>
info  - SWC minify release candidate enabled. <https://nextjs.link/swcmin>
error - ./node_modules/next/dist/client/dev/amp-dev.js

Module not found: Can't resolve 'C:\\Users\\xxx\\udemy_nextjsudemy_nextjs\\node_modules\\next\\dist\\compiled\\regenerator-runtime\\runtime.js' in 'C:\\Users\\xxx\\udemy-next-propject\\node_modules\\next\\dist\\client\\dev'
```

今回の記事はこのエラーと解決方法についてです。

## 前提

- PC: windows
- プロジェクトフォルダ名: udemy_nextjs
- create-next-app でセットアップはOK
- nextのバージョン: 12.2.2


## 調べると `ud` が原因

質問をいただいた方の場合、udemyコースだったので、プロジェクトのフォルダ名を `udemy_nextjs` にされていました。

基本的にフォルダ名が問題になることはほとんどないと思いますが、同じエラーに関して[issue](https://github.com/vercel/next.js/issues/36078)が上がっていました。

ポイントになるのはフォルダ名の `ud` の部分だということです。windowsではパスの連結にはバックスラッシュ `\` を使います。 `ud` という文字が `\` に続く形で記載されていると問題が起こるようです。

## 解決策① - nextバージョンのダウングレード

Next.jsのバージョンによって発生する問題のようなので、バージョンを下げると直るかもしれません。

12.0.4未満にすると直ったという方がいるので、下記を実行してみるといいかもしれません。

```
yern upgrade next@12.0.3
```

## 解決策② - フォルダ名の変更

`Module not found: Can't resolve` に続いて記載されているパスの中に `\\ud...` のような部分がある場合に発生しているので、そのようなフォルダ名を変更すると直るかもしれません。

今回の受講生の方の場合は、フォルダ名を変更すると無事解決できました。



## 参考
https://www.reddit.com/r/nextjs/comments/u521hp/nextjs_error_module_not_found/
https://github.com/vercel/next.js/issues/36078
JupyterLab Teradata拡張モジュール

[Teradata Vantage™ Modules for Jupyter Installation Guide](https://docs.teradata.com/r/Teradata-VantageTM-Modules-for-Jupyter-Installation-Guide) [リリース番号：6.1　リリース日付：2022/10/7]の翻訳です。

<iframe width="560" height="315" src="https://www.youtube.com/embed/dA2LTlvrAn0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# JupyterLab Teradata拡張モジュール
JupyterLabに対して、Teradata Vantageを操作するための拡張モジュールです。 Teradata Vantageにあるデータを使って、Python、R、SQLによるアクセスで操作することができます。
- JupyterLabノートブックからPython、R、またはSQLでVantageにアクセスできます。
- Teradata Vantageのデータカタログからオブジェクトを探索して利用出来ます。
- Teradataのダウンロードサイトから無償でダウンロードして利用できます。
- 手動でのJupyterLabへのインストールとDockerイメージでのインストールの2パターンから選べます。
- 言語ライブラリとを使用することで、クライアントへのデータ移動なく、インデータベースで分析できます。

### JupyterLab Teradata拡張モジュールの画面イメージ
<img width="900" alt="JupyterLab Teradata拡張モジュール.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740723/0f74cc4f-88d8-298b-a363-a74778938b77.png">

# JupyterLab Teradata拡張モジュールの機能
| 機能 | 説明 |
|:-|:-|
|ナビゲーター |Teradata Vantageでオブジェクトが表示及び参照するためのナビゲーターモジュールが含まれています。|
|コネクション・マネジャー   |ナビゲーターおよびノートブックで使用するVantageへの接続を管理できます。|
|SQLカーネル|接続管理や、SQLドライバを使用してクエリの実行などSQL実行に必要な拡張機能。|
|Python言語パッケージ|PythonからTeradata Vantageにアクセスするために用いるPhtyon用パッケージ。|
|R言語パッケージ|R言語からTeradata Vantageにアクセスするために用いるR言語用パッケージ。|
|SQLノートブックのサンプル|サンプルとなるSQLの場合のノートブック。|
|Pythonノートブックのサンプル|サンプルとなるpytonの場合のノートブック。|
|Rノートブックのサンプル|サンプルとなるRの場合のノートブック。|
|その他ライブラリ|データサイエンティスト向けのその他ライブラリ。|

# インストール方法

|インストールのパターン|説明|
|:-|:-|
|Dockerイメージ|JupyterLabとJupyterLab Teradata拡張モジュール及び関連のモジュールが含まれたDockerイメージを使いインストールします。Dockerのコンテナとして動作するため、事前にDockerをインストールいただく必要があります。|
|JupyterLab手動|JupyterLabに対して、追加でJupyterLab Teradata拡張モジュールを手動で追加いただく方法になります。そのため事前にJupyterLabをインストールいただく必要があります。|

インストール方法は、[「Jupyter NotebookからVantageを利用する方法」](https://qiita.com/ykswi/items/70f29c598c5e7314e3ea)を参照下さい。

#### インストール方法による対応機能の違い

|機能|Dockerイメージ|JupyterLab手動|
|:-|:-:|:-:|
|ナビゲーター|●|●|
|コネクション・マネジャー|●|●|
|SQLカーネル|●|●|
|Python言語パッケージ|●||
|R言語パッケージ|●||
|SQLノートブックのサンプル|●|●|
|Pythonノートブックのサンプル|●||
|Rノートブックのサンプル|●||
|その他ライブラリ|●||

## おわりに
:::note warn
警告
この本書は[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
これは引っ掛かる偽装メールが来た

# 概要
朝、OutLookメールを開いたら、このようなメールが届いていました。慌てました。こんな注文はしていません。

差出人　amazon.co.jp <noreplymail@beglobe.info>
件名　　amazon.co.jp 注文確認 #114-6942298-4134302 
 

注文確認
________________________________________こんにちは,

ありがとうございます。商品の発送時に確認をお送りします。
詳細
注文 #114-6942298-4134302　<--ここに不審なリンクボタンがある。
________________________________________ 
に送る：
ディーン
通り 221-4-12 東京都
注文合計: ¥11259JPY
注文の表示または管理　<--ここに、不審なリンクボタンがある。

	 
グーグルプレイギフトカード ¥10000
(物理的なアイテム)
注文合計: ¥11259JPY


 
________________________________________
この注文があなたではない場合,
できるだけ早くこの注文をキャンセルしてください
注文をキャンセルする　<---ここにリンクボタンがある。



________________________________________またお会いしましょう.

Amazon
# よくよく見ると
いつも利用しているアマゾンからのメールとちがう感じがします。
(1)ドメイン名がおかしい。
　　いつものドメインはAmazon.co.jpだが、このドメインは
　　amazon.co.jpとなっている。
(2)リンクボタンをホバーすると、怪しげなリンク先になっている。
(3)文章の構成や内容が変だ。
　　日本語になっていない。
# 一見するとびっくりしてしまう。
まず、こんな大金で注文はしていない。
それと、「できるだけ早くこの注文をキャンセルしてください」という文面で急いで、クリックしてしまう。
今回も、クリックしてしまった。するとAdblockの画面がでてあやしいメールとの表示がでたので、それ以上は深入りしなかった。
ここで、クリックを続けていると、とんでもないところへ引きずりこまれてしまう。早く、その泥沼から這い上がらなければならない。

# あとがき
とにかく、最近の偽装メールは巧妙になっている。まず、慌てさせる。急いでクリックしないと大変なことになると思い込ませる。
いゃー、びっくりした。振込詐欺の手口もそうだが、政府や、その他の関係セクションは、まず、落ち着いてと言うが、その場になったら、そんな忠告は忘れている。慌てふためくことになります。実は、その前日にアマゾンで買い物をしていたので、余計、アマゾンからのメールとの思い込みがあった。アマゾンから、発送しました。とのメールも来ていたので、それらのメールの一つにこのメールがあったので、つい、開いてしまった。
Pythonのインスタンス変数の定義場所と注意点


Pythonのクラスではインスタンス変数を定義できますが、定義する場所について解説してみます。

## 本記事の要約

インスタンス変数は

- 基本的に初期化メソッドで定義するのが良い。
- 通常のメソッド内で初めて定義する場合は実行順序に注意。

## いただいた質問の内容

本記事は、[Djangoのコース](https://www.takux.one/#django-ecweb-vegeket)でいただいたご質問をもとに解説するものです。質問内容を要約すると次のような感じです。

> get_querysetメソッドで定義したself.totalなどは、同じクラス内にあるget_context_dataメソッドなどでもselfの値は保持されるという解釈でいいでしょうか？
> 

```python
...
class CartListView(ListView):
    model = Item
    template_name = 'pages/cart.html'
 
    def get_queryset(self):
        cart = self.request.session.get('cart', None)
        if cart is None or len(cart) == 0:
            return redirect('/')
        self.queryset = []
        self.total = 0  # 🔴 ここでself.totalを定義
        for item_pk, quantity in cart['items'].items():
            obj = Item.objects.get(pk=item_pk)
            obj.quantity = quantity
            obj.subtotal = int(obj.price * quantity)
            self.queryset.append(obj)
            self.total += obj.subtotal
        self.tax_included_total = int(self.total * (settings.TAX_RATE + 1))
        cart['total'] = self.total
        cart['tax_included_total'] = self.tax_included_total
        self.request.session['cart'] = cart
        return super().get_queryset()
 
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        try:
            context["total"] = self.total  # 🔴 ここで使用
            context["tax_included_total"] = self.tax_included_total
        except Exception:
            pass
        return context
```

このコードをシンプルな形に直して解説してみます。


## インスタンス変数は初期化メソッドで定義するのが一番いい

まず前提として、できるならインスタンス変数は初期化メソッド（`__init__`メソッド）で設定した方がいいと思います。

例のコードにおいてはそうではなく、任意のメソッドの中で新しく定義しています。
なぜかというと、
- 継承している親クラスのメソッドが呼ばれる実行順序を知っていた

ので、わざわざ初期化メソッドを呼び出さなくてもいいかな、という判断でこのようにしました。

本記事はこのように初期化メソッドを使わずに、インスタンス変数を定義、使用する場合の挙動についての解説になります。

:::note warn
継承していても初期化メソッドを呼び出してインスタンス変数を定義することはできます。初期化メソッドの中でまず親クラスの初期化メソッドを実行してあげれば大丈夫です。
:::




## 簡単なコードで再現
では初期化メソッドを使わないでインスタンス変数を定義する場合の挙動を確認していきます。

まずは例のコードではなく簡単なコードに書き換えてみます。

```python
class Dog():

    def born(self):
        print('bornメソッドが呼ばれた。')
        self.dog = 'ワンッワンッ'

    def bark(self):
        print('barkメソッドが呼ばれた。')
        print(self.dog)
```

`self.dog` はbornメソッドで定義され、

barkメソッド内で呼び出しています。

Dogクラスをインスタンス化して実行。下記のようにうまく「ワンッワンッ」と表示されています。

```python
my_dog = Dog()
my_dog.born()
my_dog.bark()

# 実行結果 ---
# bornメソッドが呼ばれた。
# barkメソッドが呼ばれた。
# ワンッワンッ
```

## うまくいかないケース

先ほどうまくいったのは実行する順番が正しかったからです。

次のように、`my_dog.born()` を実行する前に `my_dog.bark()`  を実行すると、`self.dog` が定義されていないため、失敗することに。。。

```python
my_dog = Dog()
# my_dog.born()
my_dog.bark()

# 実行結果 ---
# barkメソッドが呼ばれた。
# Traceback (most recent call last):
# ...
# AttributeError: 'Dog' object has no attribute 'dog'
```

このように実行順序が違えばうまくいかないことが起こり得るので、
基本的な考え方としては（自分でクラスを定義するときは特に）まず初期化メソッドでインスタンス変数を定義するのがいいと思います。

継承したクラスの場合でも、実行順序がよくわからないとかであれば、初期化メソッド自体をオーバーライドして定義しておくのが無難です。



以上、なぜインスタンス変数をインスタンスメソッドの中で新しく定義したのかについての解説でした。
Node.start/3でエラーが出る場合にはepmdをバックグラウンド起動する

Elixir作者のJosé Valimに教えてもらいました．

https://github.com/elixir-lang/elixir/issues/12219

https://github.com/erlang/otp/issues/6399

# 現象

再起動した直後に `Node.start(:host, :shortnames)` を実行すると次のようなエラーになる:

```elixir
07:25:06.212 [notice] Protocol 'inet_tcp': register/listen error: econnrefused

{:error,
 {{:shutdown, {:failed_to_start_child, :net_kernel, {:EXIT, :nodistribution}}},
  {:child, :undefined, :net_sup_dynamic,
   {:erl_distribution, :start_link,
    [
      %{
        clean_halt: false,
        name: :host,
        name_domain: :shortnames,
        net_tickintensity: 4,
        net_ticktime: 60,
        supervisor: :net_sup_dynamic
      }
    ]}, :permanent, false, 1000, :supervisor, [:erl_distribution]}}}
```

# Joséの解説

https://github.com/elixir-lang/elixir/issues/12219#issuecomment-1295756745

https://github.com/erlang/otp/issues/6399#issuecomment-1295756641

> This is expected. For the Erlang distribution to work, you need `epmd` running. When you do `iex --sname` (or `erl -sname`), `epmd` is automatically started for you. However, if you kill `epmd`, you can reproduce the same failure without restarting the machine:

> これは予期された挙動です．Erlangの分散機能を動作させるためには，`empd`を実行する必要があります．もし`iex --sname` あるいは `erl -sname`を実行した場合は，`epmd`は自動的に起動します．しかし，もし `epmd` を削除した場合には，PCを再起動することなく同じFailure(故障)を再現できます．

```elixir
$ killall epmd
$ iex
Erlang/OTP 25 [RELEASE CANDIDATE 2] [erts-13.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.15.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Node.start(:host, :shortnames)

09:09:32.101 [notice] Protocol 'inet_tcp': register/listen error: econnrefused
```

> Perhaps the error message could be clearer, either by changing the exit code to `noepmd` or by also logging a clearer reason, but the behaviour is expected. :)

> おそらく、終了コードを `noepmd` に変更するか，より明確な理由をログに記録することで，エラーメッセージがより明確になる可能性があります．しかし，動作は予期されたものです。 :)

# ソリューション

というわけで，次のようなコードを書きました．

https://github.com/zacky1972/sample_port_node

このコード断片は，`Node.alive?/0`が`false`を返す(Nodeが起動していない)時に，`Node.start/3`を呼び出して起動を試みます．もしこれがエラーを返した時には，プロセスを起動して`System.cmd/3`を使って `epmd -daemon`を実行するようにします(Thanks! @mnishiguchi )． 

あと，このコードは，SHA256を使ってランダム化されたcookieを生成します．