(本格ベーコン作った)

 ベーコンが食べたくなったので本格ベーコンを作りました。

完成まではおよそ1週間かかります。

 

手順は

1、400~800g(今回は400g)程度の豚バラブロックを用意し、フォークで穴をあける。

2、ハーブ塩を作る

3、ハーブ塩を肉に刷り込む

4、ラップで包み、ジップロックに入れて冷蔵庫で4日間寝かせる。

  その間一日一回上下をひっくり返す。

5、肉にくしを指して燻製できる状態にし一夜風にあて乾燥させる。

6、60°cで6時間燻製させる。

 

【ハーブ塩の分量(肉500gに対して)】

・塩(自然塩や岩塩)……25〜30g(肉の2.5〜3%) 

・砂糖(きび糖など)……10g

 ・黒こしょう(粗挽き)……5g 

・にんにく(すりおろし)……1〜2片 

・ローリエ(砕く)……3枚 

・タイム(乾燥)……小さじ2 

・ローズマリー(乾燥・細かく刻む)……小さじ2

 ・セージ(乾燥)……小さじ1 

・オールスパイス……小さじ1/2

 

今回用意した肉は400g * 10個で合計4Kg

■作業の様子

ハーブ類

4日間漬け込んだ後の肉

つるすために針金を加工した串を刺します。

その後、扇風機を使って風乾。

七輪の上に、さくらチップを入れたフライパンを置き燻製。

途中燻せていない時間があったのでこの工程が終わるのに8時間かかりました。

■いざ実食

塩辛かったです。

もうちょっと塩の量減らしたほうが良かったかも。


おまけ

ヒバカリを見つけました。

          (VOXELAB Aquila S2の修理)

 今回は、以前ノズル詰まりで使えなくなっていた3Dプリンターを修理しました。

詳しい原因は、ヒートシンク部分に溶けたフィラメントが張り付いてしまい、フィラメントがノズル先端まで送られなくなっていたことでした。

もしかしたらPLAを有機溶剤で溶かすなどして対処できた可能性がありますが、今回はホットエンドごと新品に交換しました。値段は2,483円。

https://ja.aliexpress.com/item

 

交換後は問題なく動きました。

 

交換中の様子

交換パーツ

コメリで買ってきた修理部品

ノズル部分にアクセスするためにファンとモーターをばらします。

センサーの配線は半田付けで接続しました。
温度センサーは付属品が動作しなかったため、以前のものを流用しました。

印刷したしゃちほこ↓

            (海水魚水槽の模様替え

 今回は、海水魚水槽の掃除と模様替えを行ったので、記録として残しておこうと思います。

 

「掃除」といっても、水槽内のリセットに近い作業になります。

主に変わった点・リセットした点は次のとおりです。

・上部フィルターから外部フィルターへ交換
・飼育水は以前のものを10Lのみ残し、それ以外はすべて新しい水に交換
・これまで使用していたライブロックやあわびの貝殻は廃棄
・底砂の厚みを薄く調整
・新しいライブロックを約1kg追加

といった内容です。

 

ここからは作業の様子です。

 

まずはリセット前の状態。こんな感じで3年間やってきました。

コケも生えまくりですね。

リセット作業中は、水槽の位置も部屋の模様替えに合わせて変更しました。底砂は水道水で洗ってから投入しています。

魚たちはその間、バケツに待機です。

水を張った後は海水を作り、

ヒーターと熱湯←たぶんあんまよくない))で温度を調整していきます。

外部フィルターは、Amazonで約6000円のものを買いました。

水槽まわりをすっきりさせるために購入。静かでgoodです。

購入したライブロック

かにがなかに。

そしてリセット後の様子。夜に撮影したため、魚たちはすでに就寝モード。

サンゴも最近不調ですが、時間が解決してくれるはずです。

最後に動画

初めての大掛かりなリセットですがかなり満足できる仕上がりになりました。

今後も長年の夢であるカクレクマノミの繁殖に向けても、頑張って環境を整えていきます。

              (秋月電子の購入品メモ)

約3か月ぶり、そして今年最初の投稿です。

しばらく電子工作をさぼっていてネタがなかったのですが、今日からまた本格的に再開しようと思います。

今回は秋葉原へ行き、特に目的を決めずに部品を見ながら散策。その中で、8×8ドットマトリクスを使った砂時計を作ることにしました。

上下にドットマトリクスをつなげ、6軸IMUセンサーで傾きを検知して、本物の砂時計のように動かす予定です。複数制作も考えて、PICマイコンも購入しました。

 

そのほかに買った部品も含め、次に表でまとめておきます。

制作は準備が整い次第ということで

品名 個数 単価(円) 合計(円)
8×8ドットマトリクス(青) 2 280 560
8×8ドットマトリクス(赤) 2 180 360
8×8ドットマトリクス(黄) 2 180 370
6軸IMUセンサーモジュール 2 990 1980
LEDマトリックスドライバー (HT16K33) 2 330 660
ペルチェ素子 1 500 500
ESP32 1 1770 1770
OH182/E 2 30 60
可変スイッチング電源 1 1300 1300
XHコネクター 1 100 100
12F1822 4 200 800
合計金額 8460 円

 

 

 

 

        (DMの履歴からAIチャットボットを作成する。)

  今回はインスタのDMの履歴からAIチャットボットを機械学習させて作ってみようと思います。

 

ステップ

① DMの履歴をjson形式でダウンロード。

② 会話を機械学習できる形に整理する。

③ ollamaをインストール  ←要らなかった

④ LoRA微調整で既存の大規模llmに自分の会話風になるように重みをつける(機械学習)

⑤ テスト

⑥ 簡単なアプリケーションを作ってチャットボット化 ←次回

 

■実際に作っていく。

①DMの履歴をjson形式でダウンロード。

1、下記の要領でDMの履歴をエクスポートする画面までいく

・インスタグラムにログイン > プロフィールのはぐるまをクリック > Meta認証 > あなたの情報とアクセス許可 > あなたの情報をエクスポート

 

2、json形式でダウンロード

・下図が表示されたら「エクスポートを作成」で手順に沿いながらフォーマットをjsonダウンロードするにし、項目を「メッセージ」のみにする。

3、数時間たったら登録しているメールアドレスにzipファイルが届くのでわかりやすい場所に展開して保存する。

 

②会話を機械学習できる形にする。(パース)

◎簡単なプログラムの動作解説

1,DMしたユーザー名の下にjsonファイルがあるファイルをひとまとめにしたファイルを参照

2,文字化けを解消

3,URL、メール、電話番号などの個人情報と300字以上の長文を削除

4,DMのjson形式から会話がセットになった形式からパースする。

import json
import glob
import re
import os

BASE_DIR = r"C:\Users\ユーザー名\Desktop\DM_jsonファイル"
OUTPUT_FILE = os.path.join(BASE_DIR, "insta_finetune.jsonl")

def fix_encoding(text: str) -> str:
    """文字化けをUTF-8に戻す"""
    try:
        # 文字化けしている場合(ãなど)を再変換
        text = text.encode('latin1').decode('utf-8')
    except Exception:
        pass
    return text

def clean_text(text):
    """URL・メール・電話番号などを除去して整形"""
    if not isinstance(text, str):
        return ""
    # 文字化け修復
    text = fix_encoding(text)
    # URL削除
    text = re.sub(r"http\S+|www\.\S+", "", text)
    # メール削除
    text = re.sub(r"\S+@\S+", "", text)
    # 電話番号削除
    text = re.sub(r"\d{2,4}-\d{2,4}-\d{4}", "", text)
    # 英数字だけの文を除外
    if re.fullmatch(r"[\x00-\x7F]+", text):
        return ""
    # 絵文字削除
    text = re.sub(r"[\U00010000-\U0010ffff]", "", text)
    # 空白トリム
    text = text.strip()
    return text

train_data = []

json_files = glob.glob(os.path.join(BASE_DIR, "**", "message_*.json"), recursive=True)
print(f" 発見したJSONファイル数: {len(json_files)}")

for file in json_files:
    with open(file, encoding="utf-8") as f:
        try:
            data = json.load(f)
        except json.JSONDecodeError:
            print(f"⚠️ JSON読み込み失敗: {file}")
            continue

        messages = data.get("messages", [])
        messages = sorted(messages, key=lambda x: x.get("timestamp_ms", 0))

        for i in range(len(messages) - 1):
            m1, m2 = messages[i], messages[i + 1]
            if "content" not in m1 or "content" not in m2:
                continue

            text1 = clean_text(m1["content"])
            text2 = clean_text(m2["content"])

            if not text1 or not text2:
                continue
            if len(text1) > 300 or len(text2) > 300:
                continue

            train_data.append({"input": text1, "output": text2})

with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
    for item in train_data:
        f.write(json.dumps(item, ensure_ascii=False) + "\n")

print(f"\n✅ 完了: {len(train_data)}件の会話ペアを保存しました。")
print(f" 出力ファイル: {OUTPUT_FILE}")

 

とりあえず今回用意した機械学習用の会話ペアは3520件です。

下図がパースし終わったプログラム。

 

③ollamaをインストール

・まずollamaとは大規模言語モデルをローカルで実行できるオープンソースのツールで、windows/mac/linuxで動作します。動作もそれほど重いわけではありません。

1、https://ollama.com/downloadから自分の環境にあったものをダウンロード。

2、cmdで下記を実行。

ollama run llama3

本題とは関係ないですが、せっかくなのでollamaを動かしてみましょう。

ollamaはモデルでllmをローカルで実行するだけのツールなのでこちらで使うモデルを指定する必要があります。③ollamaをインストールのとおり今回はllama3を使ってみました。他にも「mistral」などのモデルがあります。他のモデルを使いたい場合にはollama runのあとにモデル名を記述します。

 

動作確認

→ローカルでの実行はGPUのメモリの消費が激しいです。

 RTX3050の場合はメモリ不足で計算がmaxできていない場合がありました。

 (3090欲しい)

 下の例は英語ですが、一応日本語にも対応しています。

 日本語の精度はいまいちで途中で英語になったりする。

それでは本篇へ、、、


 

④機械学習する。

・機械学習といっても計算資源がしょぼいため

 一からモデルをつくるわけにはいきません。そこでLoRAというのを使います。

 モデルの専門性を高くするという技術でファインチューニングという似たもの

 コストがかり、断念しました。

 (精度はLoRAもfine tuningもあまり変わらないらしい)

 

LoRA(Low-Rank Adaptation)

→モデルの重み行列を「低ランク分解」することで、更新するパラメータを大幅に削減できるらしい。

Efficient Fine-Tuning with LoRA for LLMs | Databricks Blog

LoRA(Low-Rank Adaptation)の理論と実践

生成AIのFine tuning(ファインチューニング)とは?基本から最新手法まで

 

・またLoRAするモデルは先ほど試したllma3では大きすぎるため、

 HuggingFaceTB/SmolLM3-3Bという軽いモデルを使います。

 そしてそのモデルを使うのにollamaは使わないのでollamaのインストールは

 必要なかった

 

・量子化について

量子化の基本的な考え方は、ニューラルネットワークで使用される数値の精度を意図的に下げることです。通常、ディープラーニングモデルの重みや活性化(ニューロンの出力)は、32ビット浮動小数点数(FP32)で表現されます。しかし大量のメモリを消費するため個人のお遊び環境では使えません。

 

そのためFP32の値を4bitや8bitに変換します。(今回は4bit)

Q (x) = round ( x S ) + Z

 

ここで、

xは元の浮動小数点数

Sはスケールファクター

Zはゼロポイント(オフセット)です。

スケールファクターSは、元の浮動小数点数の範囲を量子化後の整数の範囲にマッピングするための係数で、整数/元の幅で求まります。

ゼロポイントZは、マッピング後の値が負にならないようにするための数。

ディープラーニングモデルの量子化: PyTorchによる実践解説

 

◎ソースコード (train_lowa.py)

from datasets import load_dataset
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model

# ✅ JSONL 読み込み(そのままでOK)
dataset = load_dataset(
    "json",
    data_files="C:/Users/ユーザー名/Documents/Tbot/insta_finetune.jsonl"
)

# ✅ モデルを4bitで読み込み
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM3-3B")
model = AutoModelForCausalLM.from_pretrained(
    "HuggingFaceTB/SmolLM3-3B",
    load_in_4bit=True,
    device_map="auto"
)

# ✅ LoRA設定
lora = LoraConfig(
    r=8,
    lora_alpha=16,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]
)
model = get_peft_model(model, lora)

# ✅ トークナイズ(必要最小限)
def tokenize(example):
    text = f"ユーザー: {example['input']}\nアシスタント: {example['output']}"
    tokens = tokenizer(
        text,
        truncation=True,
        max_length=64,
        padding="max_length"
    )
    tokens["labels"] = tokens["input_ids"].copy()   # これが超重要
    return tokens


dataset = dataset.map(tokenize)

# ✅ 学習設定(3050に最適)
args = TrainingArguments(
    output_dir="out",
    per_device_train_batch_size=1,
    gradient_accumulation_steps=16,
    num_train_epochs=2,
    learning_rate=2e-4,
    fp16=True
)

trainer = Trainer(
    model=model,
    args=args,
    train_dataset=dataset["train"]
)

trainer.train()
model.save_pretrained("my-bot")

 

・このコードを動かすにはpytorchをインストールしておく必要があります。

 rtx3050用インストールコマンド(CUDA 11.8)

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

・確認コマンド

import torch
print(torch.cuda.is_available())         # True である必要あり
print(torch.cuda.get_device_name(0))     # "NVIDIA GeForce RTX 3050" と出るはず

 

◎学習結果

・以下のようなファイルができあがります。

ファイル名 / ラベル 役割 / 意味
adapter_model.safetensors 学習された LoRA 重みそのもの
adapter_config.json LoRA設定(r, α, 対象層など)
config.json 元モデルの設定コピー
generation_config.json 推論時の設定
special_tokens_map.json 特殊トークン対応
tokenizer.json / tokenizer.model トークナイザ
tokenizer_config.json トークナイザ設定
trainer_state.json 学習進行状況(loss など)
training_args.bin TrainingArgumentsの保存
events.out.tfevents... TensorBoardログ
pytorch_model.bin / .safetensors チェックポイント時点の LoRA 付きモデル
optimizer.pt オプティマイザー状態(再開用)
scheduler.pt 学習率スケジューラ状態
trainer_state.json その時点の学習情報
rng_state.pth 乱数状態
model-00001-of-00002.safetensors オフロードされたモデル分割データ
model.safetensors.index.json シャードのインデックス
zero_shard.json(ある場合) ZeROオフロード管理

 

 

⑤テスト (chat_test.py)

・とりあえずどんな対話ができるのかテストしてみます。

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch


# GPUが使えるか確認
device = "cuda" if torch.cuda.is_available() else "cpu"
print("Using device:", device)

# 学習済みモデルとトークナイザーをロード
model = AutoModelForCausalLM.from_pretrained("my-bot").to(device)
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM3-3B")

# 対話ループ
while True:
    user_input = input("ユーザー: ")
    if user_input.lower() in ["exit", "quit", "終了"]:
        break

    prompt = f"ユーザー: {user_input}\nアシスタント:"
    inputs = tokenizer(prompt, return_tensors="pt").to(device)

    outputs = model.generate(
        **inputs,
        max_new_tokens=100,
        do_sample=True,
        temperature=0.7,
        top_p=0.9
    )

    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
    print(response)

 

会話

ユーザー: こんにちは
アシスタント: すごい!
ユーザー: なにがやねん

アシスタント: 笑笑

ユーザー: 世界で一番高い山はなに?
アシスタント: アマゾン山?
ユーザー: ちゃうわ、あほやな

アシスタント: えー?笑笑笑

 

見てのとおりめちゃくちゃあほです。

しかも複数人のDMを読み込んでいるため人格が混ざっている感じがします。

もしかしたらベースのモデルを読み込めてないのかも。

やり方が間違っているかもしれないのでアプリケーションとして完成させるのはこの先になりそう。