GNN|如何做的比卷積神經(jīng)網(wǎng)絡(luò)更好?
點擊上方“小白學視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達


?
1. 層次圖

def?compute_iou_binary(seg1,?seg2):
????inters?=?float(np.count_nonzero(seg1?&?seg2))
????#區(qū)域可以預先計算
????seg1_area?=?float(np.count_nonzero(seg1))
????seg2_area?=?float(np.count_nonzero(seg2))
????return?inters?/?(seg1_area?+?seg2_area?-?inters)
def?hierarchical_graph(masks_multiscale,?n_sp_actual,?knn_graph=32):
????n_sp_total?=?np.sum(n_sp_actual)
????A?=?np.zeros((n_sp_total,?n_sp_total))
????for?level1,?masks1?in?enumerate(masks_multiscale):
????????for?level2,?masks2?in?enumerate(masks_multiscale[level1+1:]):
????????????for?i,?mask1?in?enumerate(masks1):
????????????????for?j,?mask2?in?enumerate(masks2):
????????????????????A[np.sum(n_sp_actual[:level1],?dtype=np.int)?+?i,?
????????????????????np.sum(n_sp_actual[:level2+level1+1],?dtype=np.int)?+?j]?=?compute_iou_binary(mask1,?mask2)
????sparsify_graph(A,?knn_graph)
????return?A?+?A.T
n_sp_actual?=?[]
avg_values_multiscale,?coord_multiscale,?masks_multiscale?=?[],?[],?[]
#?Scales?[1000,?300,?150,?75,?21,?7]?]在論文中
for?i,?(name,?sp)?in?enumerate(zip(['children',?'parents',?'grandparents'],?[1000,?300,?21])):
????superpixels?=?slic(img,?n_segments=sp)
????n_sp_actual.append(len(np.unique(superpixels)))
????avg_values_,?coord_,?masks_?=?superpixel_features(img,?superpixels)
????avg_values_multiscale.append(avg_values_)
????coord_multiscale.append(coord_)
????masks_multiscale.append(masks_)
A_spatial_multiscale?=?spatial_graph(np.concatenate(coord_multiscale),?img.shape[:2],?knn_graph=knn_graph)
A_hier?=?hierarchical_graph(masks_multiscale,?n_sp_actual,?knn_graph=None)
?
到目前為止,如果我們可視化濾波器,它們將看起來非常原始(就像高斯一樣)。有關(guān)更多詳細信息,請參見我的[GNN教程](https://medium.com/@BorisAKnyazev/tutorial-on-graph-neural-networks-for-computer-vision-and-beyond-part-1-3d9fada3b80d)。我們想學習一些類似于ConvNets的邊緣檢測器,因為效果很好。但是事實證明,使用GNN來學習它們非常困難。為此,我們基本上需要根據(jù)坐標之間的差異在超像素之間生成邊緣。這樣,我們將使GNN能夠理解坐標系(旋轉(zhuǎn),平移)。我們將使用在PyTorch中定義的2層神經(jīng)網(wǎng)絡(luò),如下所示:
pred_edge?=?nn.Sequential(nn.Linear(2,?32),
??????????????????????????nn.ReLU(True),
??????????????????????????nn.Linear(32,?L))
其中L是預測邊數(shù)或濾波器數(shù),例如下面的圖表中的4。
我們限制濾波器僅根據(jù) |(x?,y?) - (x?,y?)|之間的絕對差而不是原始值來學習邊緣,從而使濾波器變得對稱。?這限制了濾波器的容量,但是它仍然比我們的基準GCN使用的簡單高斯濾波器好得多。
在我的[Jupyter筆記本](https://github.com/bknyaz/bmvc_2019/blob/master/bmvc_2019.ipynb)中,我創(chuàng)建了一個LearnableGraph類,該類實現(xiàn)了在給定節(jié)點坐標(或任何其他特征)和空間圖的情況下預測邊緣的邏輯。?后者用于在每個節(jié)點周圍定義一個小的局部鄰域,以避免預測所有可能的節(jié)點對的邊緣,因為它昂貴且連接非常遠的超像素沒有多大意義。
下面,我將訓練有素的pred_edge函數(shù)可視化。?為此,我假設(shè)在其中應用卷積的索引為1的當前節(jié)點位于坐標系(x?,y?)= 0的中心。?然后,我簡單地采樣其他節(jié)點的坐標(x?,y?),并將其輸入給pred_edge。?顏色顯示邊緣的強度取決于與中心節(jié)點的距離。

學習到的圖也非常強大,但是計算量較大,如果我們生成非常稀疏的圖,則可以忽略不計。32.3%的結(jié)果僅比ConvNet低0.4%,如果我們生成更多的過濾器,則可以輕松地改善它!
?
現(xiàn)在,我們有了三個圖:空間圖,層次圖和學習圖。?具有空間或?qū)哟螆D的單個圖卷積層僅允許特征在“第一鄰居”內(nèi)傳播。?在我們的例子中,鄰居是軟性定義的,因為我們使用高斯來定義層次圖的空間圖和IoU。?(Defferrard等。 NIPS(2016))提出了一種多尺度(multihop)圖卷積算法,該算法將K-hop鄰域內(nèi)的特征聚合在一起并近似譜圖卷積。?有關(guān)此方法的詳細說明,請參見我的[其他文章](https://towardsdatascience.com/tutorial-on-graph-neural-networks-for-computer-vision-and-beyond-part-2-be6d71d70f49)。?對于我們的空間圖,它實質(zhì)上對應于使用多個不同寬度的高斯。?對于分層圖,我們可以通過這種方式在遠程子節(jié)點之間創(chuàng)建K-hop快捷方式。?對于學習的圖,此方法將創(chuàng)建可視化的學習過濾器的多個比例。
使用多尺度圖卷積,在我的GraphLayerMultiscale類中實現(xiàn),結(jié)果證明是非常重要的,它使我們的性能比基準卷積神經(jīng)網(wǎng)絡(luò)高出0.3%!
?
到目前為止,為了從我們的三個圖中學習,我們使用了標準的級聯(lián)方法。?但是,這種方法有兩個問題。?首先,這種融合算子的可訓練參數(shù)的數(shù)量是線性的。?輸入和輸出要素的維數(shù),比例(K)和關(guān)系類型的數(shù)量,因此,如果我們一次增加兩個或多個這些參數(shù),它的確會快速增長。?其次,我們嘗試融合的關(guān)系類型可以具有非常不同的性質(zhì),并占據(jù)流形的非常不同的子空間。?為了同時解決這兩個問題,我們提出了類似于(Knyazev等人,NeurIPS-W,2018)的可學習的預測。?通過這種方式,我們將線性相關(guān)性解耦,與串聯(lián)相比,參數(shù)數(shù)量減少了2-3倍。?此外,可學習的投影變換了多關(guān)系特征,因此它們應占據(jù)流形的附近子空間,從而促進信息從一種關(guān)系傳播到另一種關(guān)系。

通過使用在下面的GraphLayerFusion類中實現(xiàn)的擬議融合方法,我們將ConvNet擊敗了達到了34.5%提升1.8%,而參數(shù)卻減少了2倍!?對于最初對圖像的空間結(jié)構(gòu)一無所知的模型,除了以超像素編碼的信息外,還給人留下了深刻的印象。?探索其他融合方法(例如這種方法)以獲得更好的結(jié)果將很有趣。
class?GraphLayerFusion(GraphLayerMultiscale):
????def?__init__(self,
?????????????????in_features,
?????????????????out_features,
?????????????????K,
?????????????????fusion='pc',
?????????????????n_hidden=64,
?????????????????bnorm=True,
?????????????????activation=nn.ReLU(True),
?????????????????n_relations=1):
????????super(GraphLayerFusion,?self).__init__(in_features,?out_features,?K,?bnorm,?activation,?n_relations)
????????self.fusion?=?fusion
????????if?self.fusion?==?'cp':
????????????fc?=?[nn.Linear(in_features?*?K?*?n_relations,?n_hidden),?
??????????????????nn.ReLU(True),?
??????????????????nn.Linear(n_hidden,?out_features)]
????????else:
????????????if?self.fusion?==?'pc':
????????????????fc?=?[nn.Linear(n_hidden?*?n_relations,?out_features)]
????????????elif?self.fusion?==?'sum':
????????????????fc?=?[nn.Linear(n_hidden,?out_features)]
????????????else:
????????????????raise?NotImplementedError('cp,?pc?or?sum?is?expected.?Use?GraphLayer?for?the?baseline?concatenation?fusion')
????????????self.proj?=?nn.ModuleList([nn.Sequential(nn.Linear(in_features?*?K,?n_hidden),?nn.Tanh())?
???????????????????????????????????????for?rel?in?range(n_relations)])??#?projection?layers?followed?by?nonlinearity
????????if?bnorm:
????????????fc.append(BatchNorm1d_GNN(out_features))
????????if?activation?is?not?None:
????????????fc.append(activation)
????????self.fc?=?nn.Sequential(*fc)
????def?relation_fusion(self,?x,?A):
????????B,?N?=?x.shape[:2]
????????for?rel?in?range(self.n_relations):
????????????y?=?self.chebyshev_basis(A[:,?:,?:,?rel],?x,?self.K).view(B,?N,?-1)??#?B,N,K,C
????????????if?self.fusion?in?['pc',?'sum']:
????????????????y?=?self.proj[rel](y)??#?projection?
????????????????if?self.fusion?==?'sum':
????????????????????y_out?=?y?if?rel?==?0?else?y_out?+?y
????????????????????continue
????????????#?for?CP?and?PC
????????????if?rel?==?0:
????????????????y_out?=?[]
????????????y_out.append(y)??
????????y?=?self.fc(y_out?if?self.fusion?==?'sum'?else?(torch.cat(y_out,?2)))??#?B,N,F
????????return?y
?
事實證明,有了多關(guān)系圖網(wǎng)絡(luò)和一些技巧,我們可以比卷積神經(jīng)網(wǎng)絡(luò)做得更好!
不幸的是,在改進GNN的過程中,我們逐漸失去了不變性。例如,旋轉(zhuǎn)圖像后,超像素的形狀可能會發(fā)生變化,而我們用于節(jié)點特征以改善模型的超像素坐標也使其健壯性降低。
盡管如此,我們的工作只是邁向更好的圖像推理模型的一小步,并且我們證明了GNN可以為一個有希望的方向鋪平道路。
有關(guān)實現(xiàn)的詳細信息,請參閱我在Github上的[筆記本](https://github.com/bknyaz/bmvc_2019)。
我還高度推薦Matthias Fey的碩士論文,其中包含與非常相關(guān)的主題相關(guān)的[代碼](https://github.com/rusty1s/embedded_gcnn)。
交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學校/公司+研究方向“,例如:”張三?+?上海交大?+?視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~
