pytochでのunsqueeeとスクウェアの使い方説明
〹s queee関数:配列の形状から単次元項目を削除し、shapeの中の1次元を削除します。
()s queee()はs queee()の逆方向操作で、次元を追加します。この次元数は1で、追加の次元を指定できます。例えば、unsqueeze(a,1)は1でこの次元を追加することを表しています。
Bertモデルを学ぶには、pytochを使ってtenserの操作を行う必要があります。pytochとtenssorに慣れていないので、pytochでよく使われている、tenssor操作に関するunsqueee()、squeee()、expand()、view()、cat()とrepeat()などの手紙の数をまとめて記憶を深めます。
1、unsqueee()とスクウェア()
同時に、出力されたテンソルは元のテンソルとメモリを共有します。そのうちの一つを変えると、もう一つも変わります。
画像の次元情報は違っています。赤枠内の括弧の数は違います。
注意するのは、スクウェア()は圧縮次元が1の次元しかないことです。他のサイズは維持できません。
この関数の役割は、指定された次元を数値サイズに変更することです。次元が1の次元にしか変えられません。そうしないとエラーが発生します。変更されない次元は、-1または元の値に入ることができる。
第0次元は1から2に変更され、そのまま元のtenssorをこの次元にコピーして見ることができます。
3、repeat()
repeat(*sizes)
指定された次元に沿って元のtensorをデータコピーします。この関数はexpand()とはちょっと違います。expand()は次元が1の次元にしか拡大できませんが、repeat()はすべての次元を自由に操作できます。
cはaの対応次元に3を掛け、3を掛けて3をかける動作を示すので、c:touch.Size([6,3,2304])
a:
b
c
4、view()
tenssor.view()という関数は、reshpeのような機能を持っています。簡単に理解すると、一つのtensorを一次元のtenssorに変換してから、次元を指定するtenssorに結合します。たとえば:
また、テンソルの次元を変える必要があります。肝心な次元を知っています。手動で他の次元値を計算したくないなら、view(-1)を使ってもいいです。pytochは自動的に計算してくれます。
特に注意したいのは、view(-1、-1)のような使い方は間違います。つまりview()関数には単一-1しかないということです。
5、cat()
cat(seq,dim,out=None)は、2つ以上のtenssorをつなぎ合わせるという意味です。
seqは接続する2つのシーケンスを表し、例えば、seq=(a,b)、a,bは2つの接続可能なシーケンスである。
dimはどの次元で接続しますか?dim=0、横方向接続dim=1、縦方向接続
()s queee()はs queee()の逆方向操作で、次元を追加します。この次元数は1で、追加の次元を指定できます。例えば、unsqueeze(a,1)は1でこの次元を追加することを表しています。
import torch
a=torch.rand(2,3,1)
print(torch.unsqueeze(a,2).size())#torch.Size([2, 3, 1, 1])
print(a.size()) #torch.Size([2, 3, 1])
print(a.squeeze().size()) #torch.Size([2, 3])
print(a.squeeze(0).size()) #torch.Size([2, 3, 1])
print(a.squeeze(-1).size()) #torch.Size([2, 3])
print(a.size()) #torch.Size([2, 3, 1])
print(a.squeeze(-2).size()) #torch.Size([2, 3, 1])
print(a.squeeze(-3).size()) #torch.Size([2, 3, 1])
print(a.squeeze(1).size()) #torch.Size([2, 3, 1])
print(a.squeeze(2).size()) #torch.Size([2, 3])
print(a.squeeze(3).size()) #RuntimeError: Dimension out of range (expected to be in range of [-3, 2], but got 3)
print(a.unsqueeze().size()) #TypeError: unsqueeze() missing 1 required positional arguments: "dim"
print(a.unsqueeze(-3).size()) #torch.Size([2, 1, 3, 1])
print(a.unsqueeze(-2).size()) #torch.Size([2, 3, 1, 1])
print(a.unsqueeze(-1).size()) #torch.Size([2, 3, 1, 1])
print(a.unsqueeze(0).size()) #torch.Size([1, 2, 3, 1])
print(a.unsqueeze(1).size()) #torch.Size([2, 1, 3, 1])
print(a.unsqueeze(2).size()) #torch.Size([2, 3, 1, 1])
print(a.unsqueeze(3).size()) #torch.Size([2, 3, 1, 1])
print(torch.unsqueeze(a,3))
b=torch.rand(2,1,3,1)
print(b.squeeze().size()) #torch.Size([2, 3])
追加:pytouchにおけるunsqueeze()、スクウェア()、expand()、repeat()、view()、cat()関数のまとめBertモデルを学ぶには、pytochを使ってtenserの操作を行う必要があります。pytochとtenssorに慣れていないので、pytochでよく使われている、tenssor操作に関するunsqueee()、squeee()、expand()、view()、cat()とrepeat()などの手紙の数をまとめて記憶を深めます。
1、unsqueee()とスクウェア()
torch.unsqueeze(input, dim,out=None) → Tensor
unsqueee()の役割は与えられたtenssorの次元を増加させるために使われています。unsqueeze(dim)は次元番号がdimであるところでtenssorに1次元を増加させます。例えば、次元がtoch.Size([768])のtenssorはどうすればtoch.Size([1,768,1])になりますか?unsqueee()を使って直接コードを入れることができます。
a=torch.randn(768)
print(a.shape) # torch.Size([768])
a=a.unsqueeze(0)
print(a.shape) #torch.Size([1, 768])
a = a.unsqueeze(2)
print(a.shape) #torch.Size([1, 768, 1])
直接チェーンを使ってプログラミングすることもできます。
a=torch.randn(768)
print(a.shape) # torch.Size([768])
a=a.unsqueeze(1).unsqueeze(0)
print(a.shape) #torch.Size([1, 768, 1])
tensqueee()の処理を経た後、全体のデータ量は不変です。次元の広がりは、リストが変わらず、直接に外に幾重かの括弧を入れるのと似ています。
torch.squeeze(input, dim=None, out=None) → Tensor
スクウェアの役割は圧縮次元であり、直接次元を1とする次元を取り除くことです。形式的には、括弧を一つ取り除くという表現があります。同時に、出力されたテンソルは元のテンソルとメモリを共有します。そのうちの一つを変えると、もう一つも変わります。
a=torch.randn(2,1,768)
print(a)
print(a.shape) #torch.Size([2, 1, 768])
a=a.squeeze()
print(a)
print(a.shape) #torch.Size([2, 768])
画像の次元情報は違っています。赤枠内の括弧の数は違います。
注意するのは、スクウェア()は圧縮次元が1の次元しかないことです。他のサイズは維持できません。
a=torch.randn(2,768)
print(a.shape) #torch.Size([2, 768])
a=a.squeeze()
print(a.shape) #torch.Size([2, 768])
2、expand()この関数の役割は、指定された次元を数値サイズに変更することです。次元が1の次元にしか変えられません。そうしないとエラーが発生します。変更されない次元は、-1または元の値に入ることができる。
torch.Tensor.expand(*sizes) → Tensor
テンソルの新しいビューを返します。テンソルの単一次元をより大きなサイズに拡大できます。
a=torch.randn(1,1,3,768)
print(a)
print(a.shape) #torch.Size([1, 1, 3, 768])
b=a.expand(2,-1,-1,-1)
print(b)
print(b.shape) #torch.Size([2, 1, 3, 768])
c=a.expand(2,1,3,768)
print(c.shape) #torch.Size([2, 1, 3, 768])
bとcの次元は同じです。第0次元は1から2に変更され、そのまま元のtenssorをこの次元にコピーして見ることができます。
3、repeat()
repeat(*sizes)
指定された次元に沿って元のtensorをデータコピーします。この関数はexpand()とはちょっと違います。expand()は次元が1の次元にしか拡大できませんが、repeat()はすべての次元を自由に操作できます。
a=torch.randn(2,1,768)
print(a)
print(a.shape) #torch.Size([2, 1, 768])
b=a.repeat(1,2,1)
print(b)
print(b.shape) #torch.Size([2, 2, 768])
c=a.repeat(3,3,3)
print(c)
print(c.shape) #torch.Size([6, 3, 2304])
bはaの対応次元に1を掛け、2を掛け、1を掛ける動作を示すので、b:touch.Size([2,1,768])cはaの対応次元に3を掛け、3を掛けて3をかける動作を示すので、c:touch.Size([6,3,2304])
a:
b
c
4、view()
tenssor.view()という関数は、reshpeのような機能を持っています。簡単に理解すると、一つのtensorを一次元のtenssorに変換してから、次元を指定するtenssorに結合します。たとえば:
word_embedding=torch.randn(16,3,768)
print(word_embedding.shape)
new_word_embedding=word_embedding.view(8,6,768)
print(new_word_embedding.shape)
もちろんここで指定された次元の積は元のtenssorの次元積と同じでなければなりません。16*3*768=8*6*768また、テンソルの次元を変える必要があります。肝心な次元を知っています。手動で他の次元値を計算したくないなら、view(-1)を使ってもいいです。pytochは自動的に計算してくれます。
word_embedding=torch.randn(16,3,768)
print(word_embedding.shape)
new_word_embedding=word_embedding.view(-1)
print(new_word_embedding.shape)
new_word_embedding=word_embedding.view(1,-1)
print(new_word_embedding.shape)
new_word_embedding=word_embedding.view(-1,768)
print(new_word_embedding.shape)
その結果、-1を使うと、自動的に他の次元が得られます。特に注意したいのは、view(-1、-1)のような使い方は間違います。つまりview()関数には単一-1しかないということです。
5、cat()
cat(seq,dim,out=None)は、2つ以上のtenssorをつなぎ合わせるという意味です。
seqは接続する2つのシーケンスを表し、例えば、seq=(a,b)、a,bは2つの接続可能なシーケンスである。
dimはどの次元で接続しますか?dim=0、横方向接続dim=1、縦方向接続
a=torch.randn(4,3)
b=torch.randn(4,3)
c=torch.cat((a,b),dim=0)# , torch.Size([8, 3])
print(c.shape)
d=torch.cat((a,b),dim=1)# , torch.Size([4, 6])
print(d.shape)
もう一つの書き方があります。cat(list、dim、out=None)の中のlistの要素はtenssorです。
tensors=[]
for i in range(10):
tensors.append(torch.randn(4,3))
a=torch.cat(tensors,dim=0) #torch.Size([40, 3])
print(a.shape)
b=torch.cat(tensors,dim=1) #torch.Size([4, 30])
print(b.shape)
結果:
torch.Size([40, 3])
torch.Size([4, 30])
以上は個人の経験ですので、参考にしていただければと思います。間違いがあったり、完全に考えていないところがあれば、教えてください。