TECH PLAY

SQLite

イベント

該当するコンテンツが見つかりませんでした

マガジン

該当するコンテンツが見つかりませんでした

技術ブログ

2026年1月21日、自部署の生成AI利活用を推進する有志の集まりで主催した「Hacking Fest 2025 Winter」を開催しました。Hacking Festとは?Hacking Fest ...
SCSK いわいです。 前回はRaspberry Pi 5で気温/気圧/湿度センサーを使って測定し、 Webで表示、DBに取得データを検索するシステムを構築しました。 今回は測定したデータからAIを使って気温/気圧/湿度をリアルタイム予測してみます。 今回は前回セットアップした環境をそのまま流用します。 Raspberry Piで気温/気圧/湿度計測 結果をWebサーバで見てみよう Raspberry Pi 5で気温/気圧/湿度センサーを使って測定し、Webで表示するシステムを構築したいと思います。DBに取得データを格納し、あとから検索できるといろいろ便利です。 blog.usize-tech.com 2025.12.08   過去データから現在値を予測す る 過去データから現在値を予測します。これには機械学習結果からの推論(教師あり学習)を使用します。 温度/湿度/気圧の予測のために「線形回帰」「非線形回帰」「LSTM(Long Short Term Memory)」の3つを試してみます。 「線形回帰」はデータの関係性が直線(線形)の場合で表せる場合に使われます。 ⇒グラフにした時にだいたいまっすぐな線で表せる 例えば商品の売上と広告費用などが該当します。 「非線形回帰」は「データの関係性が曲線(非線形)」で表せる場合に使われます。 ⇒グラフにした時に曲がった線で表せる 例えば投げたボールの高さと時間の関係が該当します。 「LSTM」は時系列データや文章など、時間の流れや順番が大事なデータをうまく使える機械学習のモデルです。 ⇒過去と今の情報を組み合わせて考えられる仕組み 例えば株価の予測、文章の意味理解が該当します。 普通の再帰型ニューラルネットワークは「昔のこと」をすぐ忘れてしまいますが、LSTMは 「長い・短い記憶をうまく使い分けできる」ので、長い文章や長期的な傾向も扱えるようです。 なんだか今回のテーマに合致しそうな気配です。 ざっくりまとめると以下になります。 方式 得意なデータ 値の関係 過去の情報との関係 例 線形回帰 数値 & シンプル 直線 考慮しない 商品の売上と広告費用 非線形回帰 (RF予測) 数値 & 複雑 曲線 考慮しない 投げたボールの高さと経過時間 LSTM 時系列・文章・音声等 複雑 + 順番 重視する 株価予測、文書生成 これらの3つの方式を実装してどの予測値が実測値に近いか確認してみます。   システムのイメージ 前回作成したFlaskアプリケーションに機能を追加します。今回はWeb画面に測定結果と予測値を表示します。 蓄積した測定結果から予測モデルを作成して、予測モデルを使ってリアルタイムで現在の温度/湿度/気圧を予測してみます。 イメージはこんなカンジで。 今回のシステムで導入する機能と各ライブラリの説明は以下のとおりです。 機能 ライブラリ 説明 Webサーバ Flask 軽量なWebフレームワーク。センサー値や予測結果をWebアプリとしてブラウザに表示。 センサー通信 Smbus2 ラズパイとI2C通信する。BME280と通信するために利用。   bme280 Bosch製の温湿度・気圧センサー BME280用のPythonライブラリ。データ取得する。 データ保存 sqlite3 軽量な組み込み型データベースSQLiteを操作するためのライブラリ。計測データをローカルDBに保存・検索するために利用。 時刻処理 datetime 計測時刻の記録に利用。ローカルDBに保存するtimestampを生成。 ファイル管理 (new) os OSレベルの操作。LSTMモデル/Scalerファイル(ディープラーニング結果ファイル)の存在確認に利用。   joblib Pythonオブジェクトを高速に保存・読み込みするためのライブラリ。学習済みScalerを保存・読み込みするために利用。 数値処理 (new) numpy 数値計算ライブラリ。線形回帰やLSTMに渡すデータを配列に整形するために利用。 機械学習 (new) scikit-learn 線形回帰、非線形回帰をつかった予測のために利用。   tensorflow LSTM予測のために利用。 前回導入済みのライブラリに加え、ファイル管理用ライブラリ(joblib)、数値処理ライブラリ(numpy)、機械学習用ライブラリ(scikit-learn、tensorflow)を追加します。ファイル管理用ライブラリであるosはデフォルトでインストールされています。   過去のデータからLSTMモデルを作成する LSTMモデルを作成するために高速演算用ライブラリのnumpy、機械学習ライブラリのscikit-learnとtensorflow、ファイル生成用ライブラリjoblibをインストールします。 sudo pip install numpy –break-system-packages  sudo pip install tensorflow –break-system-packages sudo pip install scikit-learn –break-system-packages sudo pip install joblib –break-system-packages ローカルに測定結果を蓄積しているDBファイルを元にLSTMモデルとScalerファイルを生成します。 Scalerファイルとは学習時のデータの最大値/最小値、標準偏差等を求めて、それぞれのデータをを0~1の数値に 置き換えるための定義ファイルとのこと。 この定義ファイルがないとそもそもどんな情報を元に学習した結果なのかわからず、 予測もできないため、学習時と予測時には同じ定義ファイルを使う必要があります。 import sqlite3 import numpy as np import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense from sklearn.preprocessing import MinMaxScaler import joblib # スケーラー保存用 # ====== 設定 ====== DB_FILE = "bme280_data.db" TREND_WINDOW = 10 # LSTM の timesteps MODEL_FILE = "bme280_lstm_model.keras" SCALER_FILE = "bme280_scaler.save" # ====== SQLite からデータ取得 ====== def load_data(): with sqlite3.connect(DB_FILE) as conn: c = conn.cursor() c.execute(""" SELECT temperature, humidity, pressure FROM measurements ORDER BY timestamp ASC """) rows = c.fetchall() data = np.array(rows, dtype=np.float32) return data # shape = (n_samples, 3) # ====== LSTM 用系列データ作成 ====== def create_sequences(data, window_size): X, y = [], [] for i in range(len(data) - window_size): X.append(data[i:i + window_size]) y.append(data[i + window_size]) return np.array(X), np.array(y) # ====== メイン処理 ====== def main(): # --- データロード --- data = load_data() if len(data) <= TREND_WINDOW: raise ValueError("データ数が TREND_WINDOW 以下です") # --- 正規化 --- scaler = MinMaxScaler() data_scaled = scaler.fit_transform(data) # --- 系列化 --- X, y = create_sequences(data_scaled, TREND_WINDOW) print("X shape:", X.shape) # (samples, timesteps, features) print("y shape:", y.shape) # (samples, features) # --- LSTM モデル --- model = Sequential([ LSTM(32, input_shape=(X.shape[1], X.shape[2])), Dense(X.shape[2]) # temperature, humidity, pressure ]) model.compile( optimizer="adam", loss="mse" ) model.summary() # --- 学習 --- model.fit( X, y, epochs=100, batch_size=16, verbose=1 ) # --- 保存(.keras 形式) --- model.save(MODEL_FILE) joblib.dump(scaler, SCALER_FILE) print("✅ モデル保存:", MODEL_FILE) print("✅ スケーラー保存:", SCALER_FILE) # ====== 実行 ====== if __name__ == "__main__": main() 予測用に直近10件のデータを測定し、学習結果から次の1件のデータを予測するLSTMモデルを作成しています。 これで温度/湿度/気圧予測の準備ができました。   Pythonスクリプト作成/実行 今回もChatGPTを利用してPythonスクリプトを作りました。 前回の構成に過去のデータから現在の気温/湿度/気圧を線形予測、RF予測、LSTM予測した結果を 表示する機能を追加しています。 線形予測は直近5000件のデータから現在の各値を予測、RF予測は過去の測定値からランダムな特徴やデータの一部を選定、 50パターンの決定木 = forestを生成して、その平均値から各値を予測するように設計しています。 Raspberry PiでWebサーバを起動します。   実行結果 上から「実測値」、「線形予測値」、「RF予測値」、「LSTM予測値」を表示しています。 線形予測はだいぶ外れた値、RF予測は実測値にかなり近い値、LSTM予測は若干ずれた値となりました。 現実では温度/湿度/気温には以下の傾向があります。 温度:平坦⇒微増/微減⇒平坦 湿度:ジグザグ 気圧:ほぼ一定+揺れ この現象に対してそれぞれのリアルタイム予測はざっくりと以下のように動きます。 線形予測:微増/微減したら次も微増/微減するはず ⇒そもそも現実と合致してないが傾向はわかる RF予測:大体前と同じぐらいの値では? ⇒ほぼ正解 LSTM予測:過去の値からみてちょっと変えたほうがそれっぽい? ⇒賢すぎてノイズが発生することもあるがクセは覚えられる 今回のケースではそれぞれの予測は得意な分野があることがわかりました。 線形予測は「傾向予測、急激な変化を検出する」、RF予測は「リアルタイム予測、直近予測をする」、 LSTM予測は「周期的な予測、1時間後の予測をする」が得意なようです。 勉強になりました。
こんにちは AIチームの戸田です 今回は文章検索をひとつのパッケージで実現できる txtai を紹介したいと思います。 LLMは強力ですが、手元の社内資料や議事録などの固有データに関する質問には回答することができません。そこで重要になるのがRAG(Retrieval Augmented Generation)です。 固有データを検索し、関連コンテキストを取り出してPromptとしてLLMに渡すことで、固有データに関する質問に対しても回答することができるようになります。実務での活用において、現在も多くの企業がこの仕組みを使っています。 RAGは非常に強力なアプローチなのですが、固有データを保存するベクトルDBや文章を機械的に扱えるようにするためのEmbeddingなど構成が複雑になりがちで、管理コストも高くなってしまう、という課題もあります。 txtaiはall-in-one AI frameworkを自称しており上記のようなRAGによる検索システムを構築する上でややこしくなる各モジュールをひとつのパッケージとして提供しています。 本記事ではtxtaiの簡単な使い方と類似ライブラリと比較したメリットを紹介します。 txtai txtaiはPythonベースのフレームワークで、ベクトル検索やグラフ分析、リレーショナルデータベースを組み合わせたEmbeddings Databaseを中心に構成されています。 今回は扱いませんがyamlでワークフローとして定義をすることも可能なようで、応用の幅も広そうです。 環境構築 Hugging Face Transformers/Sentence Transformers、FastAPIで構成されており、Python 3.10以上の環境が必要です。今回はGoogle Colaboratoryで試します。 pipでインストールできます。 pip install txtai 基本的な使い方 以下に簡単なベクトルの類似度を利用した質問応答の例を示します。 import txtai embeddings = txtai.Embeddings() embeddings.index(["カーナビ", "ラーメン", "ダンゴムシ"]) print(embeddings.search("食べ物は?", 1)) # 第2引数の1は近傍サンプルを最大何件返すか # [(1, 0.33019936084747314)] # 出力: (index, cos類似度) indexが1、つまり"ラーメン"が最も近いという予測でもっともらしいです。import文を除くと3行で文章検索が書けてしまいました。ちなみにEmbeddingsではモデルを指定することができるのですが、デフォルトだと sentence-transformers/all-MiniLM-L6-v2 が使われるようです。 作成したindexは以下の方法でローカルファイルとして読み書きできます。 embeddings.save("{folder_name}") embeddings = Embeddings() embeddings.load("{folder_name}") これがtxtaiの最も基礎的な使い方ですが、ここから検索手法をカスタマイズすることもできます。 1. SQL txtaiは自然文クエリだけでなく、SQLでのクエリも組み合わせることができます。 embeddings = txtai.Embeddings(content=True, objects=True) embeddings.index([{ "text": "カーナビ", "n_char": 4, "text": "ラーメン", "n_char": 4, "text": "ダンゴムシ", "n_char": 5, "text": "カレーライス", "n_char": 6, }]) query = """ SELECT text, n_char FROM txtai WHERE similar('食べ物は?') AND n_char >= 6 """ print(embeddings.search(query, 2)) # [{'text': 'カレーライス', 'n_char': 6}] indexにはテキストに加え、文字数(n_char)も一緒に登録します。基礎的な使い方の部分と同じ質問を投げかけていますが6文字以上でフィルタリングしているので、"ラーメン"はヒットせず、indexに追加した"カレーライス"のみがヒットします。 2. 表層検索 ベクトル検索は優秀ですが、品番など単語の表層が重要になるケースもあります。txtaiはBM25による表層検索もサポートしており、こういったケースにも対応できます。 例えば以下の例を見てみましょう。 embeddings = txtai.Embeddings() embeddings.index(["iphone 13", "iphone 14", "iphone 15"]) print(embeddings.search("15日に買ったiphone 13", 1)) # [(2, 0.4083036184310913)] この場合"iphone 13"をヒットさせたいのですが、デフォルトのベクトル検索だと15日の方に引っ張られてしまい、indexが2、つまり"iphone 15"がヒットしてしまっています。 ここで、keyword=Trueで表層検索をすると、求める挙動通りに"iphone 13"をヒットさせることが確認できました。・ embeddings = txtai.Embeddings(keyword=True) embeddings.index(["iphone 13", "iphone 14", "iphone 15"]) print(embeddings.search("15日に買ったiphone 13", 1)) # [(0, 0.7487186789512634)] ちなみに今回は試しませんでしたが、txtai.Embeddingsでhybrid=Trueを指定すると、ベクトル検索と表層検索のハイブリッド検索も行うことができるようです。 RAG txtaiは実際にRAGを構築することもできます。以下に例を示します。Generate部分は TinySwallow-1.5B-Instruct を使用しました。GPTのようなAPI経由で一般によく使われるモデルも使用できるようなのですが、HuggingFaceに公開されているOpen Weightなモデルと簡単に連携できることがアピールされていたことが理由です。 # 架空の企業の就業規則 data = [ "勤務時間は原則9:30-18:30(休憩60分)で、フレックスはコアタイム11:00-15:00。", "月の所定労働時間は営業日数×8時間。半休は午前(9:30-13:30)と午後(14:30-18:30)。", "リモート勤務は週3日まで、申請は前日18:00までにWorkPortalで行う。", "年次有給休暇は入社日に10日付与し、以後毎年4月1日に11日、12日、…と1日ずつ加算され最大20日。", "病気休暇は年度あたり5日まで(有給とは別枠)。遅刻は30分単位で控除される。", "残業申請は当日中にSlackの#overtimeへ理由と見込み時間を投稿し、翌営業日までに精算する。" ] # IDをつける。なんでも良いが今回はuuid5 embeddings = txtai.Embeddings(content=True, autoid="uuid5") embeddings.index(data) # RAG用のPrompt Template template = """ Contextに応じて質問に答えてください。 Question: {question} Context: {context} """ # Create and run RAG instance rag = txtai.RAG( embeddings, "SakanaAI/TinySwallow-1.5B-Instruct", template=template, output="reference") # RAGの実行 resp = rag("フレックスのコアタイムは何時から何時まで?") print(resp) # {'answer': 'フレックスのコアタイムは **11:00 - 15:00** です。', 'reference': '20316a1f-6aa0-5680-97ba-b5e2e7b8461b'} # 参照先の確認 i = resp["reference"] ref = embeddings.search(f"select id, text from txtai where id = '{i}'") print(ref) # [{'id': '20316a1f-6aa0-5680-97ba-b5e2e7b8461b', 'text': '勤務時間は原則9:30-18:30(休憩60分)で、フレックスはコアタイム11:00-15:00。'}] 質問に対して正しいリファレンスをもとに答えられたことがわかるかと思います。 他のライブラリとの比較 文章検索周りでよく聞くライブラリと比較したメリットを紹介したいと思います。 LangChain LLM周りでは一番よく聞くライブラリなのではないでしょうか?正直、今回試したようなことはLangChainでも実現可能なのですが、コード量が少なくシンプルに書けるという点に関してはtxtaiが優れていると思います。一方で HyDE のような複雑なRAGを実装しようとするならばLangChainの方が柔軟性が高くて良いかもしれません。類似するライブラリとして LlamaIndex などが挙げられます Pinecone いわゆるベクトルDBです。txtaiは pip install txtai だけで動き、データはローカルファイル(SQLite等)として管理されるため、インフラ知識がなくても動かせることがメリットだと思います。類似ライブラリだと Qdrant などがあります。 FAISS Metaが開発したベクトル検索ライブラリです。最近はあまり使っていませんが、以前Chat Bot開発をしている頃はお世話になりました。非常に高速なのですが、前処理などを自分で書く必要があり、そこをよしなに済ませてくれるtxtaiはサクッと試したい時に便利だと思いました。類似するものだと Elasticsearch が代表的なものだと思います。 おわりに 本記事では文章検索を簡単に実装できるtxtaiを紹介しました。 非常に少ないコード量で書くことができ、軽いPoCなどでは活躍するのではないかと考えています。 今回は試しませんでしたが、API化を簡単にできたり、マルチモーダル対応があったりと、まだ興味深い機能があるので、また機会をみて試した上で紹介したいと思います。 最後までお読みいただき、ありがとうございました! 投稿 3行で始める文章検索 ― txtai入門 は 株式会社AI Shift に最初に表示されました。

動画

該当するコンテンツが見つかりませんでした

書籍