如果你是以下一些机器学习的消息,你肯定看到了瑞恩·达尔所做的工作自动彩色化(黑客新闻评论,reddit的评论)。这个惊人的工作是采用像素超柱状体从VGG-16网络,以便提取上色图像的信息。Samim还利用网络对黑白视频帧进行了处理,制作了以下令人惊叹的视频:
https://www.youtube.com/watch?v=_MJU8VK2PI4
着色黑白电影与神经网络(由SAMIM视频,网络由Ryan)
但如何做到这一点hypercolumns作品?如何提取他们在这样的各种像素的分类问题使用?这篇文章的主要思想是使用具有Keras和Scikit-学习VGG-16预训练的网络一起,以提取像素hypercolumns并采取目前其上的信息的肤浅的样子。我写这篇文章,因为我还没有发现在Python什么做到这一点,这可能是别人对像素分类,分割等工作真的很有用
Hypercolumns
许多使用CNNs(卷积神经网络)特征的算法通常使用FC(全连接)层特征来提取特定输入的信息。然而,最后一层FC层中的信息在空间上可能过于粗糙,无法实现精确的定位(由于maxpooling序列等),另一方面,第一层可能在空间上是精确的,但将缺乏语义信息。为了两全其美,the的作者hypercolumn纸定义“上方”该像素的像素,因为所有的CNN单元的激活矢量的hypercolumn。

在hypercolumns的提取的第一步是将图像馈送到CNN(卷积神经网络)并提取特征图激活针对图像的每个位置。最棘手的部分是,当特征地图比输入图像更小,例如一个池操作之后,该论文的作者,然后做特征映射的双线性采样,以保持特征地图上输入相同的大小。还有与对FC的issue(完全连接)层,因为你不能隔离在语义上仅绑定到图像的一个像素的单位,所以FC激活被视为1×1的特征地图,这意味着所有位置共享关于超列的FC部分的相同信息。然后,将所有这些激活连接起来,创建超列。例如,如果我们在vga -16架构中只使用最大池操作后的前2个卷积层,我们将得到一个超列,其大小为:
64个过滤器(池之前第一CONV层)
+
128过滤器(池之前第二CONV层)=192的特性
这意味着图像的每个像素将具有192维向量hypercolumn。这hypercolumn真的很有趣,因为它包含关于第一层(在这里我们有很多的空间信息,但很少语义)关于最后几层,也信息(很少的空间信息和大量的语义的)信息。因此,本hypercolumn将大量的像素分类任务一定的帮助,如一个较早的自动着色的提及,因为每个位置hypercolumn携带什么这个像素语义上和空间上代表的信息。这也是上分割任务非常有帮助亚洲金博宝的(你可以看到更多有关原始文件介绍hypercolumn概念)。
一亚洲金博宝切听起来很酷,但我们如何在实践中提取hypercolumns?
VGG-16
Before being able to extract the hypercolumns, we’ll setup the VGG-16 pre-trained network, because you know, the price of a good GPU (I can’t even imagine many of them) here in Brazil is very expensive and I don’t want to sell my kidney to buy a GPU.

要设置上Keras预训练VGG-16网络,你需要下载文件的权重从这里(具有大约500MB vgg16_weights.h5文件),然后设置的体系结构和加载使用Keras下载的权重(关于权重文件和体系结构的更多信息这里):
从matplotlib进口pyplot如PLT进口theano进口CV2进口numpy的为NP进口SciPy的从keras.models SP导入顺序从keras.layers.core进口展平,密,差从keras.layers.convolutional进口Convolution2D,MaxPooling2D从keras.layers。Convolutional import ZeroPadding2D from keras.optimizers import SGD from sklearn.manifold import TSNE from sklearn import manifold from sklearn import cluster from sklearn.preprocessing import StandardScaler def VGG_16(weights_path=None): model = Sequential() model.add(ZeroPadding2D((1,1),input_shape=(3,224,224))) model.add(Convolution2D(64, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(64, 3, 3, activation='relu')) model.add(MaxPooling2D((2,2), stride=(2,2))) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(128, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(128, 3, 3, activation='relu')) model.add(MaxPooling2D((2,2), stride=(2,2))) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(256, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(256, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(256, 3, 3, activation='relu')) model.add(MaxPooling2D((2,2), stride=(2,2))) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(512, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(512, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(512, 3, 3, activation='relu')) model.add(MaxPooling2D((2,2), stride=(2,2))) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(512, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(512, 3, 3, activation='relu')) model.add(ZeroPadding2D((1,1))) model.add(Convolution2D(512, 3, 3, activation='relu')) model.add(MaxPooling2D((2,2), stride=(2,2))) model.add(Flatten()) model.add(Dense(4096, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(4096, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(1000, activation='softmax')) if weights_path: model.load_weights(weights_path) return model
正如你所看到的,这是一个非常简单的代码(与Pytho亚洲金博宝n进口所需要的包一起)申报VGG16架构并加载预训练的权重。在此之后,我们将编译Keras模型:
模型= VGG_16('vgg16_weights.h5') sgd =sgd (lr=0.1,衰减=1e-6,动量=0.9,nesterov=True)
现在,让我们来测试使用图像网络:
im_original = cv2.resize(cv2.imread( 'madruga.jpg'),(224,224))IM = im_original.transpose((2,0,1))IM = np.expand_dims(1M,轴= 0)im_converted= cv2.cvtColor(im_original,cv2.COLOR_BGR2RGB)plt.imshow(im_converted)
图片使用
如我们所见,我们加载了图像,固定了轴,然后我们现在可以把图像输入到vgg16得到预测:
OUT = model.predict(IM)plt.plot(out.ravel())

正如您所看到的,这些是softmax层的最终激活,带有“jersey, t恤,t恤”类别的类。
提取任意特征图
现在,提取特征地图的激活,我们必须能够提取特征从网络的任意卷积层映射。我们可以通过使用编译Theano功能做到这一点get_output ()Keras的方法,如在下面的例子:
get_feature = theano.function ([model.layers [0]。get_output(train=False), allow_input_downcast=False) feat = get_feature(im) pt .imshow(feat[0][2])
特征映射
在上面的例子中,我编译Theano函数来获取3层(卷积层)的特征图,然后仅示出第三特征地图。在这里我们可以看到激活的强度。如果我们从功能,最终层激活的地图上,我们可以看到,提取的特征是比较抽象的,一样的眼睛,等看从15卷积层下面这个例子:
get_feature = theano.function([model.layers [0]。输入],model.layers [15] .get_output(列车= FALSE),allow_input_downcast =假)技艺= get_feature(IM)plt.imshow(技艺[0] [13])
更多的语义特征映射。
正如你所看到的,这第二个特征图提取更抽象的特点。而且你还可以注意到,当我们前面看到的功能相比,形象似乎更加捉襟见肘,这是因为第一个特征映射具有224×224大小,这其中有56×56,由于各层的缩小操作卷积层之前,这就是为什么我们失去了很多的空间信息。
提取超柱状体
现在,终于让我们提取层的任意一组的hypercolumns。要做到这一点,我们将定义一个函数来提取这些hypercolumns:
DEF extract_hypercolumn(型号,layer_indexes,实例):层= [model.layers [LI] .get_output(列车=假),用于在layer_indexes LI] get_feature = theano.function([model.layers [0]。输入],层allow_input_downcast =假)feature_maps = get_feature(实例)hypercolumns = []用于feature_maps convmap:用于convmap FMAP [0]:=放大的sp.misc.imresize(FMAP,大小=(224,224),模式= “F”,口译= '双线性')hypercolumns.append(放大的)返回np.asarray(hypercolumns)
正如我们看到的,这个函数需要三个参数:模型本身、用于提取超列特性的层索引列表和用于提取超列的图像实例。现在让我们测试前2个卷积层的超列提取:
layers_extract = [3,8] hc = extract_hypercolumn(model, layers_extract, im)
就这样,我们提取的每个像素的hypercolumn载体。这个“HC”可变的形状是:(192L,224L,224L),这意味着我们为224×224像素中的每一个(总共50176个像素与每个192 hypercolumn功能)192维hypercolumn。
让我们画出每个像素的超列激活的平均值:
ave = np.average (hc。Ťranspose(1, 2, 0), axis=2) plt.imshow(ave)

你可以看到,那些第一个超列激活看起来都像边缘检测器,让我们看看这些超列是如何为第22层和第29层:
layers_extract = [22,29] HC = extract_hypercolumn(模型,layers_extract,1M)平均= np.average(hc.transpose(1,2,0),轴= 2)plt.imshow(AVE)

正如我们现在看到的,这些特征实际上更抽象,语义上更有趣,但是空间信息有点模糊。
请记住,可以使用所有初始层和最终层(包括FC层)提取超列。这里我将分别提取它们,以显示它们在可视化图中的不同之处。
简单hypercolumn像素集群
现在,你可以做很多事情,你可以使用这些超列为一些任务分类像素,做自动像素着色,分割,等等。我在这里要做的只是一个实验,是使用超列(从vga -16层3、8、15、22、29),然后使用KMeans和2个集群:
米= hc.transpose(1,2,0).reshape(50176,-1)k均值= cluster.KMeans(n_clusters = 2,max_iter = 300,n_jobs = 5,precompute_distances =真)cluster_labels = k均值.fit_predict(M)imcluster = np.zeros((224224))imcluster = imcluster.reshape((224 * 224))= imcluster cluster_labels plt.imshow(imcluster.reshape(224,224),CMAP = “热”)

现在,你可以想像是多么有用hypercolumns可以像关键点提取,分割等,这是一个非常优雅的,简单实用的理念任务。亚洲金博宝
希望你喜欢!
- Christian S. Perone