如果你是以下一些机器学习的消息,你肯定看到了瑞恩·达尔所做的工作自动彩色化 (黑客新闻评论 ,reddit的评论 )。这个惊人的工作是采用像素超柱 从VGG-16网络,以便提取上色图像的信息。SAMIM 还使用的网络来处理黑白视频帧和下面产生的惊人的视频:
https://www.youtube.com/watch?v=_mjo8vk2pi4
用神经网络给黑白电影着色(Samim的视频,Ryan的网络)
但如何做到这一点hypercolumns作品?如何提取他们在这样的各种像素的分类问题使用?这篇文章的主要思想是使用具有Keras和Scikit-学习VGG-16预训练的网络一起,以提取像素hypercolumns并采取目前其上的信息的肤浅的样子。我写这篇文章,因为我还没有发现在Python什么做到这一点,这可能是别人对像素分类,分割等工作真的很有用
Hypercolumns
许多利用卷积神经网络(CNNs)特征的算法通常使用最后一个FC(完全连接)层特征来提取特定输入的信息。然而,最后一个FC层中的信息在空间上可能太粗糙,不允许精确定位(由于maxpooling的序列等),另一方面,第一层可能在空间上精确,但将缺乏语义信息。为了充分利用这两个世界的优势hypercolumn纸 定义“上方”该像素的像素,因为所有的CNN单元的激活矢量的hypercolumn。
Hypercolumn提取 (通过Hypercolumns为对象分割和细粒度本地化 )
提取高柱的第一步是将图像输入CNN(卷积神经网络 )并提取特征图激活针对图像的每个位置。最棘手的部分是,当特征地图比输入图像更小,例如一个池操作之后,该论文的作者,然后做特征映射的双线性采样,以保持特征地图上输入相同的大小。也有与FC的问题(完全连接 )层,因为可以不分离单元仅语义绑在图像的一个像素,所以FC激活被看作1×1的特征的地图,这意味着所有位置股关于hypercolumn的FC部分相同的信息。然后,所有这些激活被连接起来以创建hypercolumn。举例来说,如果我们把VGG-16架构的最大池操作后,仅使用前2卷积层,我们将与大小的hypercolumn:
64个过滤器 (池之前第一CONV层 )
+
128个过滤器 (池之前第二CONV层 )=192个功能
这意味着图像的每个像素将具有192维向量hypercolumn。这hypercolumn真的很有趣,因为它包含关于第一层(在这里我们有很多的空间信息,但很少语义)关于最后几层,也信息(很少的空间信息和大量的语义的)信息。因此,本hypercolumn将大量的像素分类任务一定的帮助,如一个较早的自动着色的提及,因为每个位置hypercolumn携带什么这个像素语义上和空间上代表的信息。这也是上分割任务非常有帮助亚洲金博宝的(你可以看到更多有关原始文件介绍hypercolumn概念)。
一亚洲金博宝切听起来很酷,但我们如何在实践中提取hypercolumns?
VGG-16
在提取高血容量之前,我们将建立VGG-16预先训练的网络,因为你知道,在巴西,一个好的GPU(我甚至无法想象其中的许多)的价格非常昂贵,我不想卖掉我的肾去买GPU。亚洲金博宝
VGG16网络架构(由志成燕等人。)
要设置上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)模型编译(优化器=sgd,loss='分类交叉熵')
现在,让我们来测试使用图像网络:
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)
图片使用
正如我们所看到的,我们加载的图像,固定轴,然后我们就可以像现在送入VGG-16得到的预测:
OUT = model.predict(IM)plt.plot(out.ravel())
预言
如您所见,这是softmax层的最终激活,该类包含“jersey,T-shirt,tee shirt”类别。
提取任意特征图
现在,提取特征地图的激活,我们必须能够提取特征从网络的任意卷积层映射。我们可以通过使用编译Theano功能做到这一点get_output() 路缘石方法,如下例所示:
get_feature = theano.function([model.layers [0]。输入],model.layers [3] .get_output(列车= FALSE),allow_input_downcast =假)技艺= get_feature(IM)plt.imshow(技艺[0] [2])
特征映射
在上面的例子中,我编译Theano函数来获取3层(卷积层)的特征图,然后仅示出第三特征地图。在这里我们可以看到激活的强度。如果我们从功能,最终层激活的地图上,我们可以看到,提取的特征是比较抽象的,一样的眼睛,等看从15卷积层下面这个例子:
获取功能=theano.函数([模型层[0].输入],模型层[15] .get_output(train=False),allow_input_downcast=False)feat=get_feature(im)节目单(专长[0][13])
更多语义特征映射。
如您所见,第二个特征映射正在提取更抽象的特征。你还可以注意到,与我们之前看到的特征相比,图像似乎更为拉伸,这是因为第一个特征地图的大小是224×224,而这个地图的大小是56×56,这是由于卷积层之前的层的缩小操作,这就是为什么我们丢失了大量的空间信息。
提取hypercolumns
现在,终于让我们提取层的任意一组的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)
正如我们所看到的,这个函数需要三个参数:模型本身、用于提取超列特征的层索引列表和用于提取超列的图像实例。现在让我们测试前两个卷积层的超列提取:
layers_extract = [3,8] HC = extract_hypercolumn(模型,layers_extract,IM)
就这样,我们提取的每个像素的hypercolumn载体。这个“HC”可变的形状是:(192L,224L,224L),这意味着我们为224×224像素中的每一个(总共50176个像素与每个192 hypercolumn功能)192维hypercolumn。
我们绘制的平均hypercolumns激活每个像素的:
平均值=np.平均值(hc.转置(1,2,0),轴=2)节目单(平均)
Hypercolumn平均层3和8。
你可以看到,那些最初的超柱激活看起来都像边缘检测器,让我们看看这些超柱在第22层和第29层是什么样子的:
layers_extract=[22,29]hc=提取超柱(模型,layers_extract,im)ave=np.平均值(hc.转置(1,2,0),轴=2)节目单(平均)
Hypercolumn平均为层22和29。
正如我们现在可以看到,功能真多抽象和语义有趣,但与空间信息有点模糊。
请记住,您可以提取使用所有的初始层,并最终层,包括FC层hypercolumns。在这里,我分别提取他们出示他们在可视化图的区别。
简单超柱像素聚类
Now, you can do a lot of things, you can use these hypercolumns to classify pixels for some task, to do automatic pixel colorization, segmentation, etc. What I’m going to do here just as an experiment, is to use the hypercolumns (from the VGG-16 layers 3, 8, 15, 22, 29) and then cluster it using KMeans with 2 clusters:
m=hc.转置(1,2,0).重塑(50176,-1)kmeans=cluster.KMeans集群(n_clusters=2,max_iter=300,n_jobs=5,precompute_distances=True)cluster_labels=kmeans.fit_predict(m)imcluster=np.0((224224))imcluster=imcluster.reforme重塑((224*224,))imcluster=群集标签节目单(imcluster.reforme重塑(224224,cmap=”热“)
KMeans使用超列进行集群。
现在您可以想象超列对于关键点提取、分割等任务有多有用了,这是一个非常优雅、简单和有用的概念。亚洲金博宝
我希望你喜欢它 !
——克里斯蒂安·S·佩隆