Transformers(3) - 質疑応答

今回は、Transformersを使って質疑応答を行います。

(Transformersのインストールは完了している想定となります。)

質疑応答

質疑応答では、コンテキスト質問からコンテキスト内に含まれる応答を抽出します。

ソースとしては、タスク名に‘question-answering’を指定したパイプラインを作成し、コンテキストと質問を渡して応答を推論します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
from transformers import pipeline

# 質疑応答のパイプラインの準備
nlp = pipeline('question-answering')

# コンテキスト
context = 'Huggingface Transformers is a deep learning framework provided by Huggingface that specializes in natural language processing. It supports both TensorFlow and PyTorch. You can use deep learning to solve natural language processing tasks such as text classification, question answering, and summary.'

# 質問
question = 'What is a natural language processing task?'

# 推論
print(nlp(question=question, context=context))

実行結果は下記の通りです。

[実行結果]

1
{'score': 0.6564476490020752, 'start': 245, 'end': 297, 'answer': 'text classification, question answering, and summary'}

スコア65で、テキスト分類、質疑応答、要約という結果になりました。

正しい応答になっていると思います。


次回は、要約を行います。

Transformers(2) - インストール/テキスト分類

今回は、Transformersのインストールとテキスト分類を行います。

Transformersのインストール

Transformersのインストールを行うためには次のコマンドを実行します。

実行環境としてはGoogle Colaboratoryを想定しています。

[Google Colaboratory]

1
!pip install transformers[ja]==4.4.2

次のような実行結果が表示されればインストールは成功しています。

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Collecting transformers[ja]==4.4.2
Downloading transformers-4.4.2-py3-none-any.whl (2.0 MB)
|████████████████████████████████| 2.0 MB 13.1 MB/s
Requirement already satisfied: filelock in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (3.0.12)
Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (21.0)
Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (2019.12.20)
Requirement already satisfied: importlib-metadata in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (4.8.1)
Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (1.19.5)
Collecting tokenizers<0.11,>=0.10.1
Downloading tokenizers-0.10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (3.3 MB)
|████████████████████████████████| 3.3 MB 56.6 MB/s
Requirement already satisfied: tqdm>=4.27 in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (4.62.2)
Collecting sacremoses
Downloading sacremoses-0.0.45-py3-none-any.whl (895 kB)
|████████████████████████████████| 895 kB 55.7 MB/s
Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (2.23.0)
Collecting fugashi>=1.0
Downloading fugashi-1.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (490 kB)
|████████████████████████████████| 490 kB 60.5 MB/s
Collecting ipadic<2.0,>=1.0.0
Downloading ipadic-1.0.0.tar.gz (13.4 MB)
|████████████████████████████████| 13.4 MB 212 kB/s
Collecting unidic>=1.0.2
Downloading unidic-1.0.3.tar.gz (5.1 kB)
Collecting unidic-lite>=1.0.7
Downloading unidic-lite-1.0.8.tar.gz (47.4 MB)
|████████████████████████████████| 47.4 MB 79 kB/s
Requirement already satisfied: wasabi<1.0.0,>=0.6.0 in /usr/local/lib/python3.7/dist-packages (from unidic>=1.0.2->transformers[ja]==4.4.2) (0.8.2)
Requirement already satisfied: plac<2.0.0,>=1.1.3 in /usr/local/lib/python3.7/dist-packages (from unidic>=1.0.2->transformers[ja]==4.4.2) (1.1.3)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (3.0.4)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (1.24.3)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (2021.5.30)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (2.10)
Requirement already satisfied: typing-extensions>=3.6.4 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->transformers[ja]==4.4.2) (3.7.4.3)
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->transformers[ja]==4.4.2) (3.5.0)
Requirement already satisfied: pyparsing>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->transformers[ja]==4.4.2) (2.4.7)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers[ja]==4.4.2) (1.15.0)
Requirement already satisfied: joblib in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers[ja]==4.4.2) (1.0.1)
Requirement already satisfied: click in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers[ja]==4.4.2) (7.1.2)
Building wheels for collected packages: ipadic, unidic, unidic-lite
Building wheel for ipadic (setup.py) ... done
Created wheel for ipadic: filename=ipadic-1.0.0-py3-none-any.whl size=13556723 sha256=868f02ff1674a53b19d8180bdf7a9473a57ab3be9cb1551291fdcb03bfb98bc5
Stored in directory: /root/.cache/pip/wheels/33/8b/99/cf0d27191876637cd3639a560f93aa982d7855ce826c94348b
Building wheel for unidic (setup.py) ... done
Created wheel for unidic: filename=unidic-1.0.3-py3-none-any.whl size=5506 sha256=8977d77c05cd5ec120e9f048171cc7fe4804c6191cb8c3dc209a1eae232c6aa8
Stored in directory: /root/.cache/pip/wheels/23/30/0b/128289fb595ef4117d2976ffdbef5069ef83be813e88caa0a6
Building wheel for unidic-lite (setup.py) ... done
Created wheel for unidic-lite: filename=unidic_lite-1.0.8-py3-none-any.whl size=47658836 sha256=05af03831b7babce0692a95538db2a5616e083838fd8a98d6336cdf8e6f9a009
Stored in directory: /root/.cache/pip/wheels/de/69/b1/112140b599f2b13f609d485a99e357ba68df194d2079c5b1a2
Successfully built ipadic unidic unidic-lite
Installing collected packages: tokenizers, sacremoses, unidic-lite, unidic, transformers, ipadic, fugashi
Successfully installed fugashi-1.1.1 ipadic-1.0.0 sacremoses-0.0.45 tokenizers-0.10.3 transformers-4.4.2 unidic-1.0.3 unidic-lite-1.0.8

テキスト分類

テキスト分類は、テキストを事前に定義されたカテゴリに分類する処理となります。

今回は文章を「ポジティブ」か「ネガティブ」かに分類してみます。

タスク名に‘sentiment-analysis’を指定したパイプラインを作成し、そのパイプラインに任意の文章を渡します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
from transformers import pipeline

# テキスト分類のパイプラインを準備
nlp = pipeline('sentiment-analysis')

# テキスト
text = 'This movie was very interesting.'

# 推論
print(nlp(text))

[実行結果]

1
2
3
4
5
6
7
8
9
Downloading: 100%
629/629 [00:00<00:00, 10.1kB/s]
Downloading: 100%
268M/268M [00:06<00:00, 45.4MB/s]
Downloading: 100%
232k/232k [00:00<00:00, 266kB/s]
Downloading: 100%
48.0/48.0 [00:00<00:00, 850B/s]
[{'label': 'POSITIVE', 'score': 0.9997621178627014}]

スコア99以上で‘POSITIVE’な文章であると判断できました。


少し文章を変更して再度テキスト分類を行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
from transformers import pipeline

# テキスト分類のパイプラインを準備
nlp = pipeline('sentiment-analysis')

# テキスト
text = 'This movie was very silly.'

# 推論
print(nlp(text))

[実行結果]

1
[{'label': 'NEGATIVE', 'score': 0.9983341693878174}]

スコア99以上で‘NEGATIVE’な文章であると判断できました。

次回は、質問応答を行います。

Transformers(1) - 概要

Transformersは、世界中で使われているデファクトスタンダードな自然言語処理の深層学習フレームワークです。

このフレームワークを使うことで、最先端の自然言語処理を体験することができます。

Transformersの概要

Transformersは、PyTorchTensorflowの両方に対応していて、深層学習を使って下記のような自然言語処理を行うことができます。

  • テキスト分類
  • 質疑応答
  • 要約
  • テキスト生成
  • 言語モデル

モデルアーキテクチャ

次のような最先端のモデルアーキテクチャを提供しています。

  • BERT
  • GPT-2
  • T5

事前学習モデル

様々な事前学習モデルが提供されており、最先端の自然言語処理アルゴリズムを容易に試すことができます。

提供されている事前学習モデルは以下のサイトで確認できます。

提供されている事前学習モデル - https://huggingface.co/transformers/pretrained_models.html


またコミュニティで提供されている学習済みモデルもあります。

The All community building the future - https://huggingface.co/models


次回は、Transformersのインストールとテキスト分類を行います。

MongoDB(42) - テキストインデックスの作成/TTLインデックスの作成

テキストインデックスの作成とTTLインデックスの作成を行います。

テキストインデックスの作成

testコレクションのnameフィールドにテキストインデックスを作成します。

テキストインデックスを作成する場合は、“text”を指定します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// テキストインデックスを作成
> db.test.createIndex({name:"text"})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1
}

// インデックスの確認
> db.test.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "name_text",
"weights" : {
"name" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
]

“name_text”というテキストインデックスを作成することができました。

TTLインデックスの作成

TTLインデックスを作成するためにはexpireAfterSecondsに秒数を指定します。

TTLインデックスに指定できるのは、Date型またはDate型を含む配列のフィールドです。

expireAfterSecondsで指定した秒数が経過したドキュメントを自動で削除することができます。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Dateフィールドを持つドキュメント作成
> db.ttltest.insert({time : ISODate("2021-06-09T10:20:05Z") } )
WriteResult({ "nInserted" : 1 })

// 作成したドキュメント確認
> db.ttltest.find()
{ "_id" : ObjectId("614bb5956e9eb9350501ee38"), "time" : ISODate("2021-06-09T10:20:05Z") }

// TTLインデックス作成
> db.ttltest.createIndex({time:1}, {expireAfterSeconds:60})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1
}

// 作成したTTLインデックスの確認
> db.ttltest.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"time" : 1
},
"name" : "time_1",
"expireAfterSeconds" : 60
}
]

// 60秒後にデータが自動削除されることを確認
> db.ttltest.find()

ttltestコレクションのtimeフィールドに、60秒でドキュメントが削除されるようにTTLインデックスを作成しました。

これでドキュメントが60秒経過後に自動的に削除されるようになります。

MongoDB(41) - インデックスの再構築

インデックスの再構築を行うと、コレクションにあるすべてのインデックスを一旦削除してインデックスを作り直します。

インデックスを再構築する理由は次の通りです。

  • データの追加や削除を行っていくうちに発生するインデックスの無駄を解消する。
  • ディスクの使用量を少なくする。

インデックスの再構築

インデックスの再構築にはreIndex()を使用します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> db.group.reIndex()
{
"nIndexesWas" : 1,
"nIndexes" : 1,
"indexes" : [
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
}
],
"ok" : 1
}

groupコレクションに対してインデックスの再構築を行うことができました。


次回は、テキストインデックスの作成とTTLインデックスの作成を行います。

MongoDB(40) - インデックスの削除

今回は、インデックスの削除を行います。

インデックスの削除

インデックスの削除にはdropIndexを使用します。

第1引数にはインデックス名を指名します。

(インデックス名はgetIndexesで取得できるnameフィールドの値です。)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> db.position.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "name_1"
}
]

> db.position.dropIndexes("name_1")
{ "nIndexesWas" : 2, "ok" : 1 }

> db.position.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]

positionコレクションのname_1インデックスを削除することができました。

次回は、インデックスの再構築を行います。

MongoDB(39) - インデックス作成のオプション

今回は、インデックス作成のオプションを確認します。

インデックス作成時のオプション

インデックスを作成する時には、オプション指定することができます。

オプションの一覧は下記の通りです。

項目名説明
backgroundバックグラウンドでインデックスを作成します。
デフォルトはfalseです。
nameインデックス名を指定します。
uniquetureを指定するとユニークインデックスを作成します。
ユニークインデックスにすると、nullは入れられません。
デフォルトはfalseです。
partialFilterExpressionフィルターを作成し、フィルターに一致したドキュメントの部分インデックスを作成します。
フィルターには以下の条件を設定できます。
・等式(key:valueまたは$eq)
$exists (trueのみ)
$gt, $gte, $lt, $lte
$type
$and

インデックスに名前を付けて、バックグラウンドで作成

memberコレクションに対して、インデックス名を”index_e_id”とし、バックグラウンドでインデックスを作成すると下記のようになります。

インデックスのオプションはcreateIndexの第2引数に指定します。

[Mongoシェル]

1
2
3
4
5
6
7
> db.member.createIndex({e_id:1}, {name:'index_e_id', background:true})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : true,
"ok" : 1
}

部分インデックスの作成

memberコレクションに対して、所属(group)が”開発1部”のドキュメントだけに対してインデックスを作成すると下記のようになります。

[Mongoシェル]

1
2
3
4
5
6
7
> db.member.createIndex({e_id:1}, {partialFilterExpression:{group:"開発1部"}})
{
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"createdCollectionAutomatically" : false,
"ok" : 1
}

次回は、インデックスの削除を行います。

MongoDB(38) - インデックスの確認・作成

インデックスの確認と作成を行います。

インデックスの確認

memberコレクションのインデックスを確認します。

インデックスの確認にはgetIndexes()を使用します。

[Mongoシェル]

1
2
> db.member.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]

_idフィールドに昇順(=1)のインデックスが作成されていることが分かります。

インデックス名(name)は_id_です。

これは自動的に作成されるデフォルトインデックスです。

インデックスの作成

memberコレクションにインデックスを作成します。

インデックスの作成にはcreateIndex()を使います。

引数にはフィールド名と昇順(=1)か降順(=-1)を指定します。

フィールド名はカンマ区切りで複数指定可能です。

[Mongoシェル]

1
2
3
4
5
6
> db.member.createIndex({LastName:1})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1

インデックスが1つから2つに増えたことが確認できます。

“ok”が1となっているのでインデックスが1つ作成されたということになります。


作成したインデックスを確認します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> db.member.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"LastName" : 1
},
"name" : "LastName_1"
}
]

デフォルトインデックス(_id)のほかに、LastNameフィールドにもインデックスが作成されていることが確認できます。

インデックス作成時にインデックス名を指定していなかったので、自動的に”LastName_1”というインデックス名になっています。


次回は、インデックス作成のオプションを確認します。

MongoDB(37) - インデックスの種類

MongoDBでは大量のデータを処理することが多いため、インデックスの作成は必須の設定と言えます。

今回はインデックスの種類についてまとめます。

インデックスの種類

MongoDBでは、次のようなインデックスの種類があります。

  • デフォルトインデックス
    _idフィールドに自動的に作成されるユニークなインデックスのことです。
    このデフォルトインデックスは削除することができません。
  • テキストインデックス
    文字列コンテンツに対するテキスト検索クエリーをサポートするインデックスのことです。
  • TTLインデックス
    特定の時間または特定の時刻に、自動的にドキュメントを削除することができるインデックスです。
  • ハッシュインデックス
    フィールド値のハッシュ値をインデックスします。
  • 地理的インデックス
    プレーンジオメトリを使用する2Dインデックスと、球面ジオメトリを使用する2Dsphereインデックスのことです。

インデックスをつけるべきフィールド

性能面の観点からインデックスをつけるべきフィールドは次の2つです。

  • 検索条件でよく使用するフィールド
  • コレクション結合のキーとなるフィールド

インデックスのデメリット

インデックスを作成すると検索を速くすることができますが、無駄なインデックスがあると次のようなデメリットが発生するので注意が必要です。

  1. 登録、更新、削除の処理が遅くなる。
  2. ディスクの使用量が多くなる。

ただ、このデメリット以上に検索がとても速くなるため、ほとんどのコレクションでインデックスを使うことになります。


次回は、インデックスの確認と作成を行います。

MongoDB(36) - 一括処理(Bulk)⑤一括削除

今回は、一括削除を行います。

一括削除処理(remove)

順次処理で一括削除を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. removeクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> var bulk = db.member.initializeOrderedBulkOp()

> bulk.find({LastName:'武元'}).removeOne()
> bulk.find({LastName:'松田'}).removeOne()
> bulk.find({LastName:'加藤'}).removeOne()

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 3,
"upserted" : [ ]
})

> db.member.find()
{ "_id" : ObjectId("613e8ff0d1340480894d324d"), "LastName" : "伊藤", "age" : 43 }

3件のドキュメントを一括で削除することができました。

Pythonで操作

上記の処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pymongo
from pymongo import MongoClient
from pymongo import DeleteOne
from pymongo.errors import BulkWriteError

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 一括入れ替え
requests = [
DeleteOne({'LastName': '武元'}),
DeleteOne({'LastName': '松田'}),
DeleteOne({'LastName': '加藤'})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 入れ替え内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

次回からは、検索を高速化するためのインデックに関する操作を行います。