เลเยอร์หม้อแปลงระดับคำตาม Pytorch และ? หม้อแปลง
ติดตั้งไลบรารีจาก PYPI:
pip install transformers-embedderหรือจาก Conda:
conda install -c riccorl transformers-embedderมันมีเลเยอร์ Pytorch และ tokenizer ที่รองรับเกือบทุกรุ่นที่ได้รับการฝึกฝนจาก HuggingFace? Transformers Library นี่คือตัวอย่างด่วน:
import transformers_embedder as tre
tokenizer = tre . Tokenizer ( "bert-base-cased" )
model = tre . TransformersEmbedder (
"bert-base-cased" , subword_pooling_strategy = "sparse" , layer_pooling_strategy = "mean"
)
example = "This is a sample sentence"
inputs = tokenizer ( example , return_tensors = True ) {
'input_ids': tensor([[ 101, 1188, 1110, 170, 6876, 5650, 102]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1]]),
'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0]])
'scatter_offsets': tensor([[0, 1, 2, 3, 4, 5, 6]]),
'sparse_offsets': {
'sparse_indices': tensor(
[
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 2, 3, 4, 5, 6],
[0, 1, 2, 3, 4, 5, 6]
]
),
'sparse_values': tensor([1., 1., 1., 1., 1., 1., 1.]),
'sparse_size': torch.Size([1, 7, 7])
},
'sentence_length': 7 # with special tokens included
}
outputs = model ( ** inputs ) # outputs.word_embeddings.shape[1:-1] # remove [CLS] and [SEP]
torch.Size([1, 5, 768])
# len(example)
5
หนึ่งในความน่ารำคาญของการใช้แบบจำลองที่ใช้หม้อแปลงคือมันไม่ได้เป็นเรื่องเล็กน้อยที่จะคำนวณคำที่ฝังคำจากการฝังตัวแบบ token sub-token ที่พวกเขาส่งออก ด้วย API นี้มันง่ายเหมือนการใช้หม้อแปลงเพื่อรับการฝังระดับคำจากทฤษฎีทุกรุ่นหม้อแปลงที่รองรับ
คลาส TransformersEmbedder มี 3 วิธีในการรับ Embeddings:
subword_pooling_strategy="sparse" : คำนวณค่าเฉลี่ยของการฝังตัวของ sub-tokens ของแต่ละคำ (เช่นการฝังตัวของ sub-tokens จะรวมเข้าด้วยกัน) โดยใช้การคูณเมทริกซ์แบบเบาบาง กลยุทธ์นี้เป็นค่าเริ่มต้นsubword_pooling_strategy="scatter" : คำนวณค่าเฉลี่ยของการฝังตัวของ sub-tokens ของแต่ละคำโดยใช้การดำเนินการกระจาย-รวบรวม มันไม่ได้กำหนด แต่ใช้งานได้กับการส่งออก ONNXsubword_pooling_strategy="none" : ส่งคืนเอาต์พุตดิบของโมเดลหม้อแปลงโดยไม่ต้องรวมกลุ่มย่อยนี่คือตารางคุณสมบัติเล็ก ๆ น้อย ๆ :
| การรวมกัน | ซึ่งกำหนด | onnx | |
|---|---|---|---|
| เบาบาง | |||
| กระจาย | |||
| ไม่มี |
นอกจากนี้ยังมีเอาต์พุตหลายประเภทที่คุณสามารถใช้พารามิเตอร์ layer_pooling_strategy :
layer_pooling_strategy="last" : ส่งคืนสถานะที่ซ่อนอยู่สุดท้ายของโมเดลหม้อแปลงไฟฟ้าlayer_pooling_strategy="concat" : ส่งคืนการเชื่อมต่อของ output_layers ที่เลือกของlayer_pooling_strategy="sum" : ส่งคืนผลรวมของ output_layers ที่เลือกของโมเดลหม้อแปลงlayer_pooling_strategy="mean" : ส่งคืนค่าเฉลี่ยของ output_layers ที่เลือกของโมเดลหม้อแปลงlayer_pooling_strategy="scalar_mix" : ส่งคืนเอาต์พุตของเลเยอร์ผสมสเกลาร์พารามิเตอร์ของ output_layers ที่เลือกของโมเดลหม้อแปลง หากคุณต้องการเอาต์พุตทั้งหมดจากโมเดล HuggingFace คุณสามารถตั้งค่า return_all=True เพื่อรับ
class TransformersEmbedder ( torch . nn . Module ):
def __init__ (
self ,
model : Union [ str , tr . PreTrainedModel ],
subword_pooling_strategy : str = "sparse" ,
layer_pooling_strategy : str = "last" ,
output_layers : Tuple [ int ] = ( - 4 , - 3 , - 2 , - 1 ),
fine_tune : bool = True ,
return_all : bool = True ,
) คลาส Tokenizer ให้วิธีการ tokenize เพื่อประมวลผลอินพุตสำหรับเลเยอร์ TransformersEmbedder ล่วงหน้า คุณสามารถส่งประโยคดิบประโยคและประโยคที่ถูกแต่งแต้มไว้ล่วงหน้าในแบทช์ มันจะประมวลผลล่วงหน้าพวกเขาส่งคืนพจนานุกรมด้วยอินพุตสำหรับโมเดล โดยผ่าน return_tensors=True มันจะส่งคืนอินพุตเป็น torch.Tensor
โดยค่าเริ่มต้นหากคุณส่งข้อความ (หรือแบทช์) เป็นสตริงมันจะใช้ tokenizer huggingface เพื่อ tokenize พวกเขา
text = "This is a sample sentence"
tokenizer ( text )
text = [ "This is a sample sentence" , "This is another sample sentence" ]
tokenizer ( text ) คุณสามารถผ่านประโยคที่ถูกเปิด tokenized (หรือชุดประโยค) ได้โดยการตั้งค่า is_split_into_words=True
text = [ "This" , "is" , "a" , "sample" , "sentence" ]
tokenizer ( text , is_split_into_words = True )
text = [
[ "This" , "is" , "a" , "sample" , "sentence" , "1" ],
[ "This" , "is" , "sample" , "sentence" , "2" ],
]
tokenizer ( text , is_split_into_words = True )ขั้นแรกให้เริ่มต้น Tokenizer
import transformers_embedder as tre
tokenizer = tre . Tokenizer ( "bert-base-cased" ) text = "This is a sample sentence"
tokenizer ( text ) {
{
'input_ids': [[101, 1188, 1110, 170, 6876, 5650, 102]],
'token_type_ids': [[0, 0, 0, 0, 0, 0, 0]],
'attention_mask': [[1, 1, 1, 1, 1, 1, 1]],
'scatter_offsets': [[0, 1, 2, 3, 4, 5, 6]],
'sparse_offsets': {
'sparse_indices': tensor(
[
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 2, 3, 4, 5, 6],
[0, 1, 2, 3, 4, 5, 6]
]
),
'sparse_values': tensor([1., 1., 1., 1., 1., 1., 1.]),
'sparse_size': torch.Size([1, 7, 7])
},
'sentence_lengths': [7],
}
text = "This is a sample sentence A"
text_pair = "This is a sample sentence B"
tokenizer ( text , text_pair ) {
'input_ids': [[101, 1188, 1110, 170, 6876, 5650, 138, 102, 1188, 1110, 170, 6876, 5650, 139, 102]],
'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]],
'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
'scatter_offsets': [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]],
'sparse_offsets': {
'sparse_indices': tensor(
[
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
]
),
'sparse_values': tensor([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
'sparse_size': torch.Size([1, 15, 15])
},
'sentence_lengths': [15],
}
padding=True และ return_tensors=True , tokenizer ส่งคืนข้อความพร้อมสำหรับรุ่น batch = [
[ "This" , "is" , "a" , "sample" , "sentence" , "1" ],
[ "This" , "is" , "sample" , "sentence" , "2" ],
[ "This" , "is" , "a" , "sample" , "sentence" , "3" ],
# ...
[ "This" , "is" , "a" , "sample" , "sentence" , "n" , "for" , "batch" ],
]
tokenizer ( batch , padding = True , return_tensors = True )
batch_pair = [
[ "This" , "is" , "a" , "sample" , "sentence" , "pair" , "1" ],
[ "This" , "is" , "sample" , "sentence" , "pair" , "2" ],
[ "This" , "is" , "a" , "sample" , "sentence" , "pair" , "3" ],
# ...
[ "This" , "is" , "a" , "sample" , "sentence" , "pair" , "n" , "for" , "batch" ],
]
tokenizer ( batch , batch_pair , padding = True , return_tensors = True ) เป็นไปได้ที่จะเพิ่มฟิลด์ที่กำหนดเองลงในอินพุตโมเดลและบอก tokenizer ว่าจะทำอย่างไรโดยใช้ add_padding_ops เริ่มต้นด้วยการเริ่มต้น Tokenizer ด้วยชื่อรุ่น:
import transformers_embedder as tre
tokenizer = tre . Tokenizer ( "bert-base-cased" )จากนั้นเพิ่มฟิลด์ที่กำหนดเองลงไป:
custom_fields = {
"custom_filed_1" : [
[ 0 , 0 , 0 , 0 , 1 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 ]
]
} ตอนนี้เราสามารถเพิ่มตรรกะการขยายสำหรับฟิลด์ที่กำหนดเองของเราเอง custom_filed_1 วิธี add_padding_ops ใช้ในอินพุต
key : ชื่อของฟิลด์ในอินพุต tokenizervalue : ค่าที่จะใช้สำหรับการขยายlength : ความยาวถึงแผ่น มันอาจเป็นค่า int หรือสองค่าสตริง subword ที่องค์ประกอบจะเป็นเบาะเพื่อให้ตรงกับความยาวของคำย่อยและ word ที่องค์ประกอบนั้นเป็นเบาะเทียบกับความยาวของแบทช์หลังจากการรวมของคำย่อย tokenizer . add_padding_ops ( "custom_filed_1" , 0 , "word" )ในที่สุดเราสามารถโทเค็นอินพุตด้วยฟิลด์ที่กำหนดเอง:
text = [
"This is a sample sentence" ,
"This is another example sentence just make it longer, with a comma too!"
]
tokenizer ( text , padding = True , return_tensors = True , additional_inputs = custom_fields )อินพุตพร้อมสำหรับรุ่นรวมถึงการยื่นแบบกำหนดเอง
>>> inputs
{
'input_ids': tensor(
[
[ 101, 1188, 1110, 170, 6876, 5650, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 101, 1188, 1110, 1330, 1859, 5650, 1198, 1294, 1122, 2039, 117, 1114, 170, 3254, 1918, 1315, 106, 102]
]
),
'token_type_ids': tensor(
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
),
'attention_mask': tensor(
[
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
),
'scatter_offsets': tensor(
[
[ 0, 1, 2, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 14, 15, 16]
]
),
'sparse_offsets': {
'sparse_indices': tensor(
[
[ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[ 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 14, 15, 16],
[ 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
]
),
'sparse_values': tensor(
[1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
1.0000, 1.0000, 0.5000, 0.5000, 1.0000, 1.0000, 1.0000]
),
'sparse_size': torch.Size([2, 17, 18])
}
'sentence_lengths': [7, 17],
}
รหัสบางส่วนในคลาส TransformersEmbedder นำมาจากไลบรารี Pytorch Scatter โมเดลที่ผ่านการฝึกอบรมและแกนกลางของโทเคนิเซอร์มาจาก? หม้อแปลง