統計初学者でもQC検定2級一発合格した勉強方法

はじめに
現在、QC検定1級や統計検定準1級などの資格を複数取得し、AIエンジニアとして働いています。しかし、学生時代は統計にほとんど触れておらず、「標準偏差って何?」というレベルから独学で統計を学び始めました。そのきっかけとなったのが、品質管理検定(QC検定)2級です。
当時は、統計の知識はほぼゼロの状態だったため、QC検定2級のテキストを読んでもまったく理解できず、相当苦戦しました。そこで同じように「統計はちょっと苦手…」という方でもQC検定2級に合格できるよう、私の経験をもとに合格ロードマップをまとめました。ぜひ参考にしてみてください。
その他の資格について気になる方はこちらの記事を参照ください。
so24.hatenablog.com
QC検定2級概要
品質管理検定(QC検定)は、品質管理に関する知識をどの程度持っているかを全国で筆記試験を行って客観的に評価を行うものです。
2級:
QC七つ道具などを使って品質に関わる問題を解決することを自らできることが求められる方々、小集団活動などでリーダー的な役割を担っており、改善活動をリードしている方々品質管理検定(QC検定)とは | 日本規格協会 JSA Group Webdesk品質管理検定(QC検定)とは | 日本規格協会
第38回QC検定(2024年9月1日実施)の統計データ
受検者データ、学校申込データ | 日本規格協会
QC検定2級は3級と比べて大幅に難易度が上がります。合格率も3級は50%程度ですが、2級は30%程度になります。 理由は、統計の基礎知識を用いた問題が増えるためです。3級では統計をあまり意識しなくても解ける問題が多いのに対し、2級は統計をしっかり理解していないと解けない問題が増えます。ただし、統計さえ押さえてしまえば、難易度が高い試験ではありません。
【ロードマップ】QC検定2級合格までのステップ
STEP1 入門レベルの統計学を学ぶ
まずは入門レベルの統計学を網羅的に学べる書籍を一冊こなすところから始めましょう。統計の初歩的な概念が頭に入っていないと、QC検定2級のテキストは難しく感じます。
おすすめ書籍
理由は数式が少なくて、具体例が多いので初学者でも理解しやすいと思ったからです。実際に私もこの書籍で初めて統計の勉強をしました。
STEP2 QC検定2級テキスト(手法編) + QC検定2級模擬問題集
基礎的な統計知識を習得したら、QC検定2級公式テキストの手法編に取り組みましょう。同時に、模擬問題集を利用して理解度を確認します。
- テキストを読む
- 読んだ範囲の模擬問題を解く
- 解説を読んで復習する
これを各章ごとに繰り返すイメージです。手法編は計算や理解が必要な内容が多く、時間がかかります。模擬問題集は章別に分かれていて、レベルもそこまで高くないため、この段階での力試しに最適です。
STEP3 QC検定2級テキスト(実践編) + QC検定2級模擬問題集
次に、実践編にも同じ要領で取り組みます。
- 実践編を通読する
- その範囲の模擬問題を解いて復習する
実践編は暗記が多いため、深く理解するよりも、必要な知識を短期間で覚えることがポイントです。大事なところは過去問でも繰り返し出題されるので、完璧に理解できなくても過去問演習で補えます。
STEP4 QC検定2級過去問12回分(2冊分)を解く
ある程度テキストや模擬問題をこなしたら、過去問に本格的に着手します。過去問集は2冊分(12回分)の演習を推奨します。
- まずは制限時間を気にせず解く
- 解説を読み、なぜ間違えたかをしっかり分析
- 1週間後に間違えた問題だけ再挑戦し、定着度を確認
慣れてきたら試験時間90分を意識しながら、7割以上の正答率を目標に解きましょう。最終的に80分で8割以上取れるようになれば、本番は余裕を持って解けるはずです。
過去問の解答時間を短縮するコツはこちらの記事で紹介しています。
so24.hatenablog.com
STEP5 過去問の復習と受験テキストの復習
直前期は、過去問で間違えた問題の復習が最優先。さらに、テキストを再確認し、暗記漏れや苦手な分野をつぶしていきます。
- 過去問の間違いノートやメモをしっかり活用
- 実践編は暗記中心なので、短期集中で詰め込む
試験本番
手法編は計算に時間がかかるため、また試験での緊張や焦りによる計算ミスを防ぐためにも、暗記で解ける実践編から着手し、確実に得点を狙うのがおすすめです。
まとめ:統計初学者でも合格できる
「統計が難しそう…」と感じるかもしれませんが、しっかりとしたロードマップに沿って学習を進めれば、統計初学者でもQC検定2級は合格可能です。ぜひ上記のステップを参考にして、合格を勝ち取ってください。合格を応援しています。
Python × Seleniumで始めるWebスクレイピング(Microsoft Edge)
Webスクレイピングは、Webサイト上の情報をプログラムを使って自動的に取得・加工する技術です。本記事では、Selenium を使って Microsoft Edge の操作を自動化し、Webスクレイピングを行う方法をご紹介します。
Python と組み合わせることで、ログインやクリック操作などを含む動的なページからもデータを取得することが可能になります。
Selenium は、Webアプリケーションのテスト自動化ツールとして広く利用されているライブラリです。ブラウザを自動的に操作し、 などをコードで実行できます。Pythonをはじめ、さまざまなプログラミング言語から利用できる点も大きな魅力です。
人間が手動で行うテストに比べて、スピード・正確性が大幅に向上します。
継続的インテグレーション(CI)パイプラインに組み込み、コードの変更があるたびに自動テストを実行可能です。 ログインやボタンクリック、ページのスクロールなど、ユーザー操作を伴うデータ取得も自動化できます。
動的に切り替わるタブやモーダルウィンドウなどにも対応できます。 定型業務をスクリプト化して、人手作業を削減できます。ミスを減らし、作業効率を高められます。
既存システムのフロントエンドを直接操作できるため、大掛かりなシステム改修が不要です。
スクレイピング対象のサイトがスクレイピングを許可しているか、利用規約を事前に確認しましょう。 time.sleep()を活用したり、適切なリクエスト間隔をあけたりしてサーバーへの負荷を抑えましょう。 IDやパスワード、クッキーなどの認証情報を扱う場合は、セキュリティに注意が必要です。 WebDriverのバージョンとブラウザのバージョンが合っていないと正常に動かない場合があります。
本記事では、selenium==4.27.1 を使用しています。 Seleniumは実際にブラウザを自動操作するため、各ブラウザに対応したWebDriverを用意する必要があります。ここでは Microsoft Edge WebDriver を使用します。 Microsoft Edge WebDriver
するとスムーズに実行できます。
find_element() では、以下のセレクタを使用して要素を特定できます。 今回はWikipediaでポメラニアンという犬の犬種を検索し情報を取得します。 "右クリック"→"開発ツールで調査する"をクリックするとWebページのHTMLを表示できます。 今回は赤枠内の情報を取得します。 本記事では、Python × Selenium × Microsoft Edge の組み合わせでWebスクレイピングを行う手順の概要を紹介しました。
はじめに
Seleniumとは?
Seleniumでできること
Web APIとWebスクレイピングの違い
特徴
Web API
Webスクレイピング
データ形式
構造化データ (JSON, XML)
非構造化データ (HTML, テキスト)
公式サポート
あり
なし
認証・セキュリティ
高い (APIキー、OAuth)
低い(セキュリティ対策を回避する場合もある)
制限や規約
利用回数制限や有料プランがある
利用規約違反やアクセス拒否のリスク
適用範囲
提供されている機能やデータに限定される
制限なし(ただし技術的困難がある場合も)
主な使用例
地図情報、SNSデータ、気象データ取得
ウェブサイト上のテキストや画像取得
スクレイピング時の注意点
環境構築
1. Seleniumのインストール
まずは以下のコマンドでインストールしましょう。pip install selenium
2. WebDriverの準備
ダウンロード先:
Microsoft Edge WebDriver (英語) |Microsoft Edge 開発者
説明:
WebDriver を使用して Microsoft Edge を自動化する - Microsoft Edge Developer documentation | Microsoft Learn
ダウンロードした msedgedriver.exeの、
よく使用するSeleniumのメソッド
メソッド/プロパティ
概要
driver.get(url) 指定したURLのページを開きます
find_element(By, 値) 指定したセレクタに合致する最初の要素を取得します
find_elements(By, 値) 指定したセレクタに合致するすべての要素をリストで取得します
send_keys("文字列") 入力フィールドなどに文字列を入力します
click() 要素をクリックします
element.text 要素に含まれるテキストを取得します
switch_to.frame()
iframe 要素にフォーカスを移動します
default_content()
iframe から抜け出し、親のコンテキストに戻ります
quit() 全ブラウザウィンドウを閉じ、WebDriverプロセスを終了します
close() 現在アクティブなブラウザタブのみを閉じます
back() ブラウザの「戻る」操作を実行します
forward() ブラウザの「進む」操作を実行します
refresh() ページをリロード(再読み込み)します
implicitly_wait(秒数) 要素が見つかるまでの待ち時間を暗黙的に設定します
clear() テキスト入力フィールドの内容をクリアします
セレクタ一覧
セレクタ
定数
説明
例
ID
By.ID ID属性で検索
find_element(By.ID, 'username')
クラス名
By.CLASS_NAME クラス名で検索
find_element(By.CLASS_NAME, 'login-button')
タグ名
By.TAG_NAME タグ名で検索
find_element(By.TAG_NAME, 'input')
名前
By.NAME name属性で検索
find_element(By.NAME, 'email')
リンクテキスト
By.LINK_TEXT リンクのテキストで検索
find_element(By.LINK_TEXT, '詳細はこちら')
部分一致リンクテキスト
By.PARTIAL_LINK_TEXT 部分一致で検索
find_element(By.PARTIAL_LINK_TEXT, '詳細')
XPath
By.XPATH XPathで検索
find_element(By.XPATH, "//div[@class='header']")
CSSセレクタ
By.CSS_SELECTOR CSSセレクタで検索
find_element(By.CSS_SELECTOR, '.button.submit')
サンプルコード
ライブラリーのインポート
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.common.by import By
Edgeを起動して、対象のページを開く。
# msedgedriver.exe があるパスを指定
service = Service("./edgedriver_win64/msedgedriver.exe")
# Edgeを起動
driver = webdriver.Edge(service=service)
# Wikipedia日本語版のページを開く
driver.get("https://ja.wikipedia.org/wiki/ウィキペディア日本語版")
開発ツールを起動して検索ボックスのclassを探す。
ここからアクセスしたい情報を取得してきます。
今回はfind_elementのclass_nameを使用するため、classを探していきます。

Wikipediaでポメラニアンについて検索
#検索ボックスのCLASS_NAMEを指定
search_box = driver.find_element(By.CLASS_NAME, "cdx-text-input__input")
#検索ボックスに"ポメラニアン"を入力
search_box.send_keys("ポメラニアン")
#検索ボタンのCLASS_NAMEを指定
search_button = driver.find_element(By.CLASS_NAME, "cdx-search-input__end-button")
#ボタンをクリック
search_button.click()
ポメラニアンの情報を取得

#赤枠内のテーブルのCLASS_NAMEを指定
table = driver.find_element(By.CLASS_NAME, "infobox.biota")
#テキストを出力
table.text.split("\n")
出力結果['ポメラニアン',
'別名 ドイチェスピッツ (Deutscher Spitz)',
'愛称 ポム-ドッグ(Pom-Dog)',
'ポム-ポム(Pom-Pom)',
'タンブルウィード(Tumbleweed)',
'原産地 ドイツ',
'隠す',
'特徴',
'体重 3-6 kg',
'体高 13-28 cm',
'外被 ダブルコート',
'毛色 ホワイト、ブラック、ブラウン、レッド、オレンジ、クリーム、セーブル、ブラック・アンド・タン、ブラウン・アンド・タン、スポット、ブリンドル(虎毛)、そしてこれらのカラーのコンビネーション',
'隠す',
'主要畜犬団体による分類と標準',
'FCI Group 5 Section 4 #97 標準',
'AKC Toy 標準',
'ANKC Group 1 (Toys) 標準',
'CKC Group 5 (Toys) 標準',
'JKC 第5グループ 標準',
'KC (UK) Toy 標準',
'NZKC Toy 標準',
'UKC Companion Breeds 標準',
'イヌ (Canis lupus familiaris)']
まとめ
簡単に自動化することができるので、ぜひ試してみてください。
【若手でも大丈夫】QC検定1級を一発で取得した勉強法

はじめに
社会人4年目の時にQC検定1級を取得しました。今回はQC検定1級の勉強方法を記事にまとめます。これから勉強される方の参考になれば幸いです。
その他の資格について気になる方はこちらの記事を参照ください。
so24.hatenablog.com
受験前の状況
QC検定2、3級は取得済み。
実務経験も多少ありました。
受験のきっかけ
QC検定2級を取得し、QCについてもっと学んでみたいと思いました。また、職場で1級を持っている人はいなかったので、1級を取得し職場の人が知らない知見を業務に活かしたいと思ったことがきっかけでした。
QC検定1級概要
品質管理検定(QC検定)は、品質管理に関する知識をどの程度持っているかを全国で筆記試験を行って客観的に評価を行うものです。
QC検定1級の対象:品質管理部門のスタッフ、技術系部門のスタッフなど企業内において品質管理全般についての知識が要求される業務にたずさわる方々
品質管理検定(QC検定)とは | 日本規格協会
概要を見ると一見難しそうに思えますが、製造業の人であれば押さえておきたい内容が多く、実務経験が浅くてもしっかり勉強すれば合格できると思います。
逆にいくら実務経験が豊富でも勉強しないと合格は難しいと思います。
QC検定1級合率
直近の第36回の合格率は1.6%と非常に低いです。
私が受験した回は10%程度の合格率でした。
受検者データ、学校申込データ | 日本規格協会
QC検定1級の勉強方法
使用した教材
勉強スケジュールと勉強時間
勉強期間:約6ヶ月(約255時間)


勉強方法
QC検定1級は手法編と実践編という分野があります。手法編は統計的な計算がメインになります。一方、実践編はQC関連の用語や仕組みの理解がメインになります。
勉強の進め方としては、計算が多く難しい手法編を先に進め、暗記で対策できる実践編は後回しにしました。
①過去問を解いて理解する。
まずは過去問を解いて試験内容を把握しました。
試験問題はマーク式約100問+論述を120分で解き終える必要があります。しかも半数程度は計算問題のため、かなりの計算スピードが求められます。論述問題も何を書くかあらかじめ準備しておく必要があることがわかりました。
②QC検定受検テキスト→演習問題を解く。
QC検定受検テキストで知識をインプットし、演習問題を解きアウトプットしました。
③(論述以外の)過去問を解く。
過去問を解き、わからなかったらテキストで確認をしました。この段階ではあまりスピードは意識せず、確実に解くことを意識していました。
④模擬問題集で論述を解く。
論述の勉強は模擬問題集が良いです。例題が豊富で、解答案も載っているため、どのレベルで書けばよいか把握することができます。また、この模擬問題も使って、自分自身の事例で論述を書く練習をしました。
⑤(マーク+論述)過去問を解く。
試験日が近づいてきたら、過去問を暗記するくらい解きなおしました。QC検定1級は問題数が多く、時間との勝負のため問題をゆっくり考えている余裕はありません。この頃はマークは70分以内で解けるようにスピードを意識して練習をしていました。
時間を短縮するために私がやっていた方法
手法編
手法編は「問題を見て10秒以内に解法が思い浮かぶか」ということを過去問で何度も確認しました。この時は問題は解かずに、解法が思い浮かぶかということを意識していました。仕事の昼休みなどの隙間時間でもできるのでオススメです。
実践編
実践編は時間短縮のため、全ての問題は読まずに、空欄の前後やキーワードだけで回答できるように練習をしました。
試験本番
QC検定1級のテストは手法編→実践編という並びになっているため、順番通り手法編から取り組みましたが、試験当日は緊張していたため1問目からテンパっていました。そこで、実践編から先に解き、慣れてきたところで手法編を解くように咄嗟に変更しました。実践編が解き終わる頃には緊張も無くなっていたので、手法編の方も集中して解くことができました。
マーク式(手法編+実践編)は85%くらいの正答率だったと思います。
論述の方は準備していた内容が使えなかったため、その場で完全アドリブで解きました。正直あまり良い内容は書けませんでしたが合格することができました。採点はそれほど厳しくないなのかもしれません。
まとめ
QC検定1級は合格率が低く難しく思われていますが、解答スピードが重要であることを意識してしっかりと勉強することができれば合格できると思います。
頑張ってください!
【リモートワークエンジニア厳選】在宅ワークを快適にするおすすめグッズ10選

こんにちは!私は未経験からAIエンジニアになり、現在はリモートワーク(在宅ワーク)が中心の働き方をしています。最初は簡素な作業環境しかなく、会社支給のノートPC1台で仕事をしていましたが、半年かけて少しずつ快適な環境を整えてきました。
この記事では、「本当に買ってよかった!」と感じたアイテムを10個紹介しています。これからリモートワークを始める方や、自宅での作業効率・快適性を高めたい方の参考になれば嬉しいです。
リモートワークおすすめグッズ
1位. G 29インチ ウルトラワイドモニター 29WP500-B
- 特徴:ウルトラワイドで横長ディスプレイ。2つのウインドウを並べて快適作業。
- おすすめポイント:
・複数ドキュメントやアプリの同時閲覧に最適
・ PCゲームをしないので、高スペック不要ならこれで十分
・120cm幅の机でも無理なく設置可能
3位. ロジクール MX KEYS S アドバンスド ワイヤレス イルミネイテッド キーボード
4位. Flexispot 電動昇降デスク
- 特徴:高さをボタン1つで昇降調整
- おすすめポイント:
・自分の身長や好みに合わせてベストな高さを設定
・長時間の座り作業に疲れたら、スタンディング姿勢で気分転換
5位. オカムラ シルフィー オフィスチェア
- 特徴:背中のカーブや座面位置を調整して体格に合わせやすい
- おすすめポイント:
・前傾姿勢をサポートし、長時間のPC作業でも疲れにくい
・リモートワークで座る時間が長い人に最適
6位. Shokz(ショックス) OpenFit Air
- 特徴:オープン型イヤホンで自分の声がこもらない
- おすすめポイント:
・オープン型なのでリモート会議で自分の声がこもらない
・つけていることを忘れるほど装着感◎
7位. サンワサプライ ドッキングステーション
- 特徴:ケーブル1本でノートPCと周辺機器を一括接続
- おすすめポイント:
・1mケーブルでデスク裏に隠しやすく、配線スッキリ
・PD100W対応で大型ノートPCの充電も安心
9位. Quntis モニターライト ディスプレイライト
- 特徴:モニターの上に取り付けるだけで省スペース
- おすすめポイント:
・手元だけを照らして画面への反射を低減
・BenQの上位モデルより安価で十分な機能
30代未経験から始める!AIエンジニアへの最短ロードマップとおすすめ勉強法

はじめに
30代からまったくの未経験で新しい分野に挑戦することは勇気が必要です。特にAIエンジニアやデータサイエンティストを目指す場合、学ぶ範囲がとても広く、「何から手をつけるべきか」迷う方も多いでしょう。
この記事では、私が未経験からAIエンジニアになるまでに実際に行った勉強内容や取得資格をまとめ、重要度やコスパを★1~★5で評価しています。あくまで個人的な見解ですが、これからAIを学ぼうとしている方に少しでも役立つ情報になれば嬉しいです。
資格を取得するメリット
- 客観的なスキル証明ができる
- 継続して学習できることをアピールできる
- 最新技術へのキャッチアップが可能
AIの分野は変化が速く、勉強を続ける意欲を示すことが重要です。資格勉強にはそれなりの時間と費用が必要ですが、「未経験でも新しい技術を身につけようとしているんだな」と周囲に理解してもらえるメリットも大きいです。
統計検定 2級 ★★★★★
レベル:統計検定2級は大学基礎課程(1・2年次学部共通)
おすすめする人: すべてのAIエンジニア・データサイエンティスト志望者
AIやデータ分析において、統計学の基礎知識は不可欠です。統計検定2級を取得すれば、統計基礎を体系的に学習でき、実務でも「最低限の統計リテラシーを持っている」ことを証明しやすくなります。
統計検定2級|統計検定:Japan Statistical Society Certificate
統計検定 準1級 ★★★★☆
レベル:大学において統計学の基礎的講義に引き続いて学ぶ応用的な統計学の手法。
おすすめする人:理系出身者や数学に抵抗がない人。
統計検定2級よりも出題範囲が広く、難易度は格段に上がります。幅広い統計手法を学びたい人や、より実務での応用範囲を広げたい人におすすめ。ただし、時間対効果(コスパ)は人によって変わるので、数学が苦手な方にはあまり向かないかもしれません。
統計検定準1級|統計検定:Japan Statistical Society Certificate
私の準1級の勉強法は下記にまとめています。
so24.hatenablog.com
統計検定 1級 ★☆☆☆☆
レベル:大学専門課程(3・4年次)
おすすめする人:数学が得意・研究職や高度な統計理論が必要な人
統計検定1級は高度な統計理論が多く、実務でフルに活かせる場面は限られます。大学入試に近い内容も含まれるため、未経験からいきなり狙うのはコスパが悪いです。高度な研究領域や専門職を目指す方以外にはあまりおすすめしません。
統計検定1級|統計検定:Japan Statistical Society Certificate
G検定 ★★★★☆
レベル:AI・ディープラーニングの基礎知識。
おすすめする人:AIに興味のある全ての方
G検定はAIやディープラーニングの基本概念を幅広く学べる資格で、比較的合格しやすいです。ただし、資格そのものが直接的に高評価される機会は多くありません。AI分野への入り口として、最低限の知識習得のために受けるのは十分に意義があります。
G検定とは - 一般社団法人日本ディープラーニング協会【公式】
E資格 ★★★☆☆
レベル:ディープラーニングの理論と実践。
おすすめする人:理論的背景も含めてAIを深く学びたい人、費用を負担できる人
E資格は認定プログラムの受講が必要で、最低10万円以上の費用がかかります。理論から実装までを体系的に学べるため、AI開発における全体像をつかみたい方には魅力的。ただし、「実務でE資格レベルの範囲をすべて担当することはまれ」なので、予算と学習目的をよく考えて検討しましょう。
E資格とは - 一般社団法人日本ディープラーニング協会【公式】
私の勉強方法は以下の記事でまとめています。
so24.hatenablog.com
プログラミング学習
AIエンジニアやデータサイエンティストとしてPythonなどを扱う場面は多いです。未経験の場合、まずは基礎文法を把握するだけでもOK。必要に応じて実際のプロジェクトや業務の中で覚えていくほうが、効率的にスキルを身につけられます。
[講座]Tech Academy(Python+データサイエンス+AIコース) ★★★★☆
レベル:初心者向け
おすすめする人:プログラミング経験がまったくない方、独学に不安がある方
Tech Academyはメンターサポートが充実しており、疑問点を質問しながら進められるので挫折しにくいです。カリキュラムも実践的で、未経験からのスタートには最適だと感じました。
![]()
[書籍]東京大学のデータサイエンティスト育成講座 ★★★★★
レベル:初心者向け
おすすめする人:AIエンジニア志望、データ分析を基礎から学びたい方
Pythonを中心に、データ分析で必要となるプログラミング知識を一通り学べます。これ1冊をしっかり理解すれば、実務でも通用するレベルの基礎力が身につくでしょう。
[書籍]Kaggleで勝つデータ分析の技術 ★★★★☆
レベル:初級~中級者
おすすめする人: Kaggleや機械学習の実践手法を学びたい方
データサイエンスの実践的な流れを掴むことができます。中には難しい部分もありますが、最初から全て理解する必要はありません。「こういう技術やフレームワークがあるんだ」と知るだけでも大きな収穫です。
[コンペ]Kaggleなど ★★★☆☆
レベル:中級者以上
おすすめする人:実際のデータを扱いながらスキルを伸ばしたい方
未経験の方がいきなりKaggleでメダルを狙うのはかなりハードルが高いです。経験者や仲間と協力して参加するなら有益な学びになりますが、一人で挑むと行き詰まりやすいかもしれません。実務で成果を上げる方がコスパは高い場合も多いので、状況に合わせて選びましょう。
その他
業務に活かす ★★★★★
レベル:-
おすすめする人:全員
資格や勉強だけで終わらせず、ぜひ学んだ知識を社内データや個人のプロジェクトで活用してみてください。実際に分析してみることで、驚くほど理解が深まりますし、周囲からの評価も高まります。効果測定や数値化ができると、転職でも強いアピールポイントになるはずです。
さいごに
私自身が「これで良かった」と思う学習ロードマップは、次の5ステップです。
+ 統計検定2級:統計の基礎を体系的に学び、リテラシーを身につける
- G検定:AIやディープラーニングの基本概念を短期間で習得
- 東京大学のデータサイエンティスト育成講座(書籍):Python実践の基礎をしっかり固める
- Kaggleで勝つデータ分析の技術(書籍):データ分析の実務に活かせる実践的な流れを学ぶ
- 業務活用(自社データ分析やプロジェクト参加):学んだ知識を使って実績を残し、自分の価値を高める
30代未経験でも、学ぶ意欲さえあればAIエンジニアへの道は開けます。資格取得や勉強方法で迷っている方の参考になれば幸いです。あなたの成功を心から応援しています!
埋め込みモデルe5-mistral-7b-instructを使ってみた。
概要
埋め込みモデルe5-mistral-7b-instructを使って、テキスト間のコサイン類似度を計算する方法をまとめる。
※内容が間違っている可能性があります、ご容赦ください。
e5-mistral-7b-instruct
今回使用する、埋め込みモデルです。
2024年2月17日現在、MTEB LeaderboardのEnglishで4位となっています。
多言語でも使えますが、英語の使用が勧められています。
実装
こちらを参考に実装しています。
import torch import torch.nn.functional as F from torch import Tensor from transformers import AutoTokenizer, AutoModel import numpy as np from sklearn.metrics.pairwise import cosine_similarity
def last_token_pool(last_hidden_states: Tensor, attention_mask: Tensor) -> Tensor: left_padding = (attention_mask[:, -1].sum() == attention_mask.shape[0]) if left_padding: return last_hidden_states[:, -1] else: sequence_lengths = attention_mask.sum(dim=1) - 1 batch_size = last_hidden_states.shape[0] return last_hidden_states[torch.arange(batch_size, device=last_hidden_states.device), sequence_lengths]
documents = [
"次の日は良い天気です",
"明日の天気は晴れです",
"明日の天気は雨です",
"晴れが好きです",
"私はリンゴが好きです"
]
tokenizer = AutoTokenizer.from_pretrained('intfloat/e5-mistral-7b-instruct')
model = AutoModel.from_pretrained('intfloat/e5-mistral-7b-instruct')
max_length = 4096
# 入力テキストをトークン化する batch_dict = tokenizer(documents, max_length=max_length - 1, return_attention_mask=False, padding=False, truncation=True)
# eos_token_idをすべてのinput_idsに追加する batch_dict['input_ids'] = [input_ids + [tokenizer.eos_token_id] for input_ids in batch_dict['input_ids']] batch_dict = tokenizer.pad(batch_dict, padding=True, return_attention_mask=True, return_tensors='pt') outputs = model(**batch_dict) embeddings = last_token_pool(outputs.last_hidden_state, batch_dict['attention_mask'])
# 埋め込みを正規化する embeddings = F.normalize(embeddings, p=2, dim=1) embeddings_list = embeddings.tolist()
def similarity(query_embedding, document_embedding): query_embedding = np.array(query_embedding) document_embedding = np.array(document_embedding) # NumPy配列を2次元配列に変換 query_embedding = query_embedding.reshape(1, -1) document_embedding = document_embedding.reshape(1, -1) result = cosine_similarity(query_embedding, document_embedding) return result
cos_similarity=[] for i in range(len(embeddings)-1): cos_similarity.append(similarity(embeddings_list[0], embeddings_list[i+1])) print(f"query={documents[0]}") for text, score in zip(documents[1:], cos_similarity): print(f"text={text}, score={score[0][0]}")
query=次の日は良い天気です text=明日の天気は晴れです, score=0.89586343422919 text=明日の天気は雨です, score=0.8419866323866365 text=晴れが好きです, score=0.8280332788608935 text=私はリンゴが好きです, score=0.6293116246996098
結果
コサイン類似度を計算すると、「次の日は良い天気です」に対して、「明日の天気は晴れです」が高いスコアとなっていました。
疑問点
今回はクエリと指示の部分は削除して使用していますが、この使用方法が正しいのかわかっていません。
【LangChain】Ensemble Retrieverを使ってみた。
概要
LangChainのEnsemble Retrieverの使い方をまとめる。
今回はBM25、HuggingFace(sonoisa)、OpenAI(text-embedding-ada-002)の3つでEnsemble Retrieverを使ってみます。
Ensemble Retriever
検索精度を向上させるために、複数の検索結果を使用して順位を計算します。(ハイブリット検索)
バージョン
langchain==0.1.6
langchain-openai=0.0.5
実装
ライブラリのインポート
import os from langchain.retrievers import BM25Retriever, EnsembleRetriever from langchain_community.vectorstores import FAISS from langchain_openai import OpenAIEmbeddings from langchain.embeddings import HuggingFaceBgeEmbeddings from sklearn.metrics.pairwise import cosine_similarity from langchain.vectorstores.utils import DistanceStrategy from typing import List from langchain.retrievers.bm25 import default_preprocessing_func
テキストのサンプル
sentences = ["明日の天気は晴れです", "明日の天気は雨です", "晴れが好きです","私はリンゴが好きです"] query1 = "次の日は良い天気です" query2 = "私はミカンが好きです"
OpenAIのAPIKEYを設定
API_KEYは事前に環境変数に登録しておきます。
環境変数の登録方法は以下の記事に書かれています。
api_key = os.environ["OPENAI_API_KEY"]
BM25
BM25はそのまま日本語では使えないようなので、
preprocess_funcに日本語の分かち書きに適した関数を与えます。
以下の記事を参考にしています。
def generate_character_ngrams(text, i, j, binary=False): """ 文字列から指定した文字数のn-gramを生成する関数。 :param text: 文字列データ :param i: n-gramの最小文字数 :param j: n-gramの最大文字数 :param binary: Trueの場合、重複を削除 :return: n-gramのリスト """ ngrams = [] for n in range(i, j + 1): for k in range(len(text) - n + 1): ngram = text[k:k + n] ngrams.append(ngram) if binary: ngrams = list(set(ngrams)) # 重複を削除 return ngrams def preprocess_func(text: str) -> List[str]: i, j = 1, 3 if len(text) < i: return [text] return generate_character_ngrams(text, i, j, True)
bm25_retriever = BM25Retriever.from_texts(
sentences, preprocess_func=preprocess_func, metadatas=[{"source":1}]*len(sentences)
)
bm25_retriever.k = 4
scores = bm25_retriever.vectorizer.get_scores(preprocess_func(query1)) print("query=", query1) for text, score in zip(sentences, scores): print(text, score)
query= 次の日は良い天気です 明日の天気は晴れです 0.274919929536986 明日の天気は雨です 0.2903841755734415 晴れが好きです 0.2453950779493872 私はリンゴが好きです 0.274919929536986
「次の日は良い天気です」に対して、「明日の天気は雨です」が上位にきました。
正解を選択できませんでした。
scores = bm25_retriever.vectorizer.get_scores(preprocess_func(query2)) print("query=", query2) for text, score in zip(sentences, scores): print(text, score)
query= 私はミカンが好きです 明日の天気は晴れです 0.274919929536986 明日の天気は雨です 0.2903841755734415 晴れが好きです 0.2453950779493872 私はリンゴが好きです 2.681446396908925
「私はミカンが好きです」に対して、「私はリンゴが好きです」が上位にきました。
こちらは正解を選択できています。
HuggingFace
embeddingのモデルはsonoisaを使用しました。 huggingface.co
model_name = "sonoisa/sentence-bert-base-ja-mean-tokens-v2" model_kwargs = {'device': 'cuda'} #cpuの場合は'cpu' encode_kwargs = {'normalize_embeddings': True} embeddings_hf = HuggingFaceBgeEmbeddings( model_name=model_name, model_kwargs=model_kwargs, encode_kwargs=encode_kwargs ) faiss_vectorstore_hf = FAISS.from_texts(sentences, embeddings_hf, distance_strategy = DistanceStrategy.MAX_INNER_PRODUCT) faiss_retriever_hf = faiss_vectorstore_hf.as_retriever(search_kwargs={"k":4})
result_hf = faiss_retriever_hf.get_relevant_documents(query1) print("query=", query1) for doc in result_hf: print(doc)
query= 次の日は良い天気です page_content='明日の天気は晴れです' page_content='晴れが好きです' page_content='明日の天気は雨です' page_content='私はリンゴが好きです'
「次の日は良い天気です」に対して、「明日の天気は晴れです」が上位にきました。
正解を選択できています。
result_hf = faiss_retriever_hf.get_relevant_documents(query2) print("query=", query2) for doc in result_hf: print(doc)
query= 私はミカンが好きです page_content='私はリンゴが好きです' page_content='晴れが好きです' page_content='明日の天気は雨です' page_content='明日の天気は晴れです'
「私はミカンが好きです」に対して、「私はリンゴが好きです」が上位にきました。
こちらも正解を選択できています。
OpenAI
embeddings_ada = OpenAIEmbeddings(model="text-embedding-ada-002", openai_api_key=api_key) faiss_vectorstore_ada = FAISS.from_texts( sentences, embeddings_ada, metadatas=[{"source":2}]*len(sentences) ) faiss_retriever_ada = faiss_vectorstore.as_retriever(search_kwargs={"k":4}, distance_strategy = DistanceStrategy.MAX_INNER_PRODUCT)
result_ada = faiss_retriever_ada.get_relevant_documents(query1) print("query=", query1) for doc in result_ada: print(doc)
query= 次の日は良い天気です
page_content='晴れが好きです' metadata={'source': 2}
page_content='明日の天気は晴れです' metadata={'source': 2}
page_content='明日の天気は雨です' metadata={'source': 2}
page_content='私はリンゴが好きです' metadata={'source': 2}
「次の日は良い天気です」に対して、「晴れが好きです」が上位にきました。
正解を選択できませんでした。
result_ada = faiss_retriever_ada.get_relevant_documents(query2) print("query=", query2) for doc in result_ada: print(doc)
query= 私はミカンが好きです
page_content='私はリンゴが好きです' metadata={'source': 2}
page_content='晴れが好きです' metadata={'source': 2}
page_content='明日の天気は雨です' metadata={'source': 2}
page_content='明日の天気は晴れです' metadata={'source': 2}
「私はミカンが好きです」に対して、「私はリンゴが好きです」が上位にきました。
こちらは正解を選択できています。
Ensemble Retriever
上記3つの検索結果を使用してハイブリット検索してみます。
Ensemble Retrieverのコードを見てみると、以下の計算式で最終スコアを計算しているようです。
c: int = 60 rrf_score = weight * (1 / (rank + self.c))
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, faiss_retriever,faiss_retriever_hf], weights=[0.33, 0.33, 0.33]
)
docs = ensemble_retriever.invoke(query1) print("query=", query1) docs
query= 次の日は良い天気です [Document(page_content='明日の天気は晴れです'), Document(page_content='晴れが好きです'), Document(page_content='明日の天気は雨です'), Document(page_content='私はリンゴが好きです')]
「次の日は良い天気です」に対して、「明日の天気は晴れです」が上位にきました。
正解を選択できています。
docs = ensemble_retriever.invoke(query2) print("query=", query2) docs
query= 私はミカンが好きです [Document(page_content='私はリンゴが好きです'), Document(page_content='晴れが好きです'), Document(page_content='明日の天気は雨です'), Document(page_content='明日の天気は晴れです')]
「私はミカンが好きです」に対して、「私はリンゴが好きです」が上位にきました。
こちらも正解を選択できています。
結果
sonoisaとensembleで欲しかった結果が得られました。
今回のような単純な文章であればはsonoisa単体でも良い結果が得られましたが、
複雑な文章であれば、ensemble retrieverを使ったほうが検索精度の向上が見込まれると思います。
| モデル | 次の日は良い天気です | 私はミカンが好きです |
|---|---|---|
| BM25 | 明日の天気は雨です | 私はリンゴが好きです |
| sonoisa | 明日の天気は晴れです | 私はリンゴが好きです |
| ada | 晴れが好きです | 私はリンゴが好きです |
| ensemble | 明日の天気は晴れです | 私はリンゴが好きです |
![[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。] [商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]](https://hbb.afl.rakuten.co.jp/hgb/39eb8426.0db9d24d.39eb8427.a28d3a4e/?me_id=1377402&item_id=10492716&pc=https%3A%2F%2Fimage.rakuten.co.jp%2Fksdenki%2Fcabinet%2Fimages%2F41_1%2F4989027021341_1.jpg%3F_ex%3D240x240&s=240x240&t=picttext)