keras图像分类模型
Applications of machine learning (ML) are now almost an integral part of our everyday life. From a speech-recognition based virtual assistant in our smartphones to super-intelligent automated drones, ML and artificial intelligence (AI) is revolutionizing the dynamics of human-machine interactions. AI algorithms, especially the convolution neural networks (CNN) have made computer vision extremely powerful than ever. While the applications of it are breathtakingly awesome, it could be very intimidating to build one’s own CNN model, especially for a non-programmer or a beginner in data science, in general. As an R lover, it was not difficult for me to assert that it gets even more enigmatic for a novice R programmer. The plausible reason for this imbalance could be that the standard neural network and ML libraries (like Keras and Tensorflow) are primarily compatible with Python and naturally gravitate the masses to roll with Python itself, leading to a severe lack of novice’s guide and documentation to facilitate the implementation of these sophisticated frameworks in R. Nevertheless, APIs of Keras and Tensorflow is now available on CRAN. Herein, we are going to make a CNN based vanilla image-classification model using Keras and Tensorflow framework in R. With this article, my goal is to enable you to conceptualize and build your own CNN models in R using Keras and, sequentially help to boost your confidence through hands-on coding to build even more complex models in the future using this profound API. Apart from the scripting of the model, I will also try as much to concisely elaborate on the necessary components while plunging the hardcore underlying mathematics. Now let’s start.
现在,机器学习(ML)的应用几乎已经成为我们日常生活中不可或缺的一部分。 从我们智能手机中基于语音识别的虚拟助手到超智能自动无人机,机器学习和人工智能(AI)都在改变人机交互的动力。 人工智能算法,尤其是卷积神经网络(CNN)使计算机视觉变得前所未有的强大。 尽管它的应用令人叹为观止,但构建一个自己的CNN模型可能会非常令人生畏,尤其是对于一般非数据科学的程序员或初学者而言。 作为R的爱好者,我很难断言它对于R的新手程序员来说更加神秘。 造成这种不平衡的合理原因可能是标准神经网络和ML库(例如Keras和Tensorflow)主要与Python兼容,并且自然吸引了广大群众使用Python本身,从而导致新手指南和文档严重缺乏这些复杂的框架在R中的实现。尽管如此,KRANs和Tensorflow的API现在可以在CRAN上使用。 在本文中,我们将使用R中的Keras和Tensorflow框架制作基于CNN的香草图像分类模型。本文旨在帮助您使用Keras在R中概念化和构建自己的CNN模型,并依次帮助通过动手编写代码,使用深厚的API来构建更复杂的模型,从而增强您的信心。 除了模型的脚本编写之外,我还将尝试尽可能多地简要阐述必要的组件,同时降低核心数学基础。 现在开始。
As a prelude to the scripting of CNN, let’s understand the formalisms of it in brief. Just like a human eye registers the information only in the confined receptive frame and learns the specific patterns and spatial features, which subsequently trigger specific neural responses, a CNN model operates in the same fashion. We will try to probe the CNN architecture and understand its key components (Figure 1).
作为CNN脚本编写的序言,让我们简要了解一下CNN的形式主义。 就像人眼仅在受限的接受框架中注册信息并了解特定的模式和空间特征(随后触发特定的神经React)一样,CNN模型以相同的方式运行。 我们将尝试探究CNN架构并了解其关键组件(图1)。
Image by author) 作者提供的图像)Instead of amalgamating the entire image pixels at a time, a subset of pixels is convoluted into a single datum Figure 2. Convolution is carried out by sliding a frame of a smaller size across the entire image acting as a receptive field that accounts for the temporal-spatial features. This frame is called a Kernel/Filter. Imagine scanning a building wall with a flashlight, the filter works in the same fashion. Now, if you have a variety of filters, you are likely to extract or observe more discriminative spatial features and frequently recurring adjacent values. This scheme empowers the learning by not only preserving the spatial characteristics with the least information loss but also significantly reduces the required number of weights, enabling the image classification practically feasible and scalable. For example, consider a 2D black and white (b&w) image as the input to CNN. The model initiates to convolute the image by employing a filter which then slides across the image with a given step size, also called strides. The filter values are analogous to the weights in the neural network. The linear combination of these filter values and the image’s foregrounding pixel values at an instance, generate a single feature output. A set of these values generated produces a new layer called a feature map. Intuitively, a feature map is a condensed form of the input image that preserves all the dominating features and patterns into a smaller dimension for efficient learning.
代替一次将整个图像像素合并,而是将一个像素子集卷积为单个数据(图2) 。 卷积是通过在整个图像上滑动较小尺寸的帧来实现的,该帧充当了说明时空特征的接收场。 该框架称为内核/过滤器。 想象一下,用手电筒扫描建筑物的墙壁,过滤器的工作方式相同。 现在,如果您有各种过滤器,则可能会提取或观察到更具区分性的空间特征,并且经常重复出现相邻的值。 该方案不仅通过保留信息损失最少的空间特征,而且还显着减少了所需的权重数,从而使学习成为可能,从而使图像分类切实可行且可扩展。 例如,将2D黑白(b&w)图像视为CNN的输入。 该模型发起通过使用过滤器,然后在图像上具有给定步长大小,也称为步幅滑动以卷积的图像。 过滤器值类似于神经网络中的权重。 这些滤镜值与实例中图像的前景像素值的线性组合会生成单个特征输出。 生成的一组这些值会生成一个称为要素图的新图层。 直观上,特征图是输入图像的压缩形式,它将所有主要特征和模式保留为较小的维度,以进行有效学习。
Image by author) 作者提供)Elucidating this in Figure 3, the filter of size 4x4 is employed over a b&w image of dimension 10X10. The filter slides across the image with a stride of 1 unit, thus generating a convoluted layer of dimension (10–4+1)X(10–4+1) i.e 7X7. Note that the bias/intercept for this example is assumed to be 0. Similarly, n number of filters would generate n feature maps.
在图3中对此进行了说明,在尺寸为10X10的黑白图像上采用了尺寸为4x4的滤镜。 滤镜以1步的跨度在图像上滑动,从而生成尺寸为(10–4 + 1)X(10–4 + 1)的卷积层,即7X7。 注意,此示例的偏差/截距假定为0。类似地, n个滤波器将生成n个特征图。
Image by author) 作者提供的图像)For a b&w image, the depth is 1 and so of the filters. However, a colored image is an ensemble of Red, Blue, and Green (RBG) channels. precisely, a stack of three 2D layers, where each layer represents the intensity of a particular color channel. So for a colored image of depth 3, you will need a filter of dimension (4X4)X3 (Figure 4).
对于黑白图像,深度为1,以此类推。 但是,彩色图像是红色,蓝色和绿色(RBG)通道的集合。 准确地说,是三个2D层的堆栈,其中每个层代表特定颜色通道的强度。 因此,对于深度为3的彩色图像,您将需要一个尺寸为(4X4)X 3的滤镜(图4)。
Once the feature maps are generated, an activation function is applied over each of them. For this purpose, the Rectified Linear Unit (ReLU) activation function comes in handy. If the input to ReLU is a negative value, it simply transforms it to zero else it will spit out the very same input value (Figure 4). Mathematically, f(x)= max(0,x).
生成特征图后,将激活功能应用于每个特征图。 为此,整流线性单元(ReLU)激活功能 派上用场。 如果ReLU的输入为负值,它将简单地将其转换为零,否则将吐出非常相同的输入值(图4)。 数学上, f(x)= max(0,x)。
Image by author) 作者提供的图像)After the activation layer, another scheme is employed to smartly reduce the dimensions of the feature map without losing vital information. This technique is called Max-pooling. Quite similar to the convolution scheme, here only the highest value from the max-pooling window is picked. This window slides in the same fashion as of the filter but with a step-size equal to the dimension of the pooling window (Figure 5). Max-pooling significantly reduces the dimension of the feature map while also preserving the important/dominating features. The final max-pooled layer is then squashed and flatten into the neuron layer that connects to a fully connected neural network to perform the classification task.
在激活层之后,采用另一种方案来巧妙地缩小特征图的尺寸,而不会丢失重要信息。 这种技术称为最大池化。 与卷积方案非常相似,这里仅从最大池窗口中选取最大值。 该窗口以与过滤器相同的方式滑动,但步长等于池化窗口的尺寸(图5)。 最大池化显着减小了特征图的尺寸,同时还保留了重要/主要特征。 然后将最终的最大池化层压缩并压平成神经元层,该神经元层连接到完全连接的神经网络以执行分类任务。
Mind you CNN is not limited to a single convolution or a single set of the aforementioned schemes. Backed with a sufficient number of filters, The deeper your network is, the higher performance it will achieve. Intuitively, the initial convolutions would capture the low-level recurring features such as edges and colors. Sequentially, the deep layers tend to capture high-level features like recurring clusters pixels say eyes or noses in a portrait. So, in conclusion, based on your image complexity and computation power, you should choose a sufficient and efficient number of layers and filters.
请注意,您的CNN不仅限于单个卷积或上述方案的单个集合。 有足够数量的过滤器作为后盾,您的网络越深入,它将实现的性能就越高。 直观地,初始卷积将捕获低级重复特征,例如边缘和颜色。 顺序地,深层倾向于捕获高级特征,例如重复出现的簇像素表示肖像中的眼睛或鼻子。 因此,总而言之,根据图像的复杂性和计算能力,您应该选择足够和有效数量的层和滤镜。
Now let’s jump into the making of our toy model 🤓!!
现在开始制作玩具模型toy!
I believe that to understand any statistical concept nothing comes handier than a deck of playing cards. Here I will exploit a deck of playing cards but in a slightly unorthodox form. Yes, you guessed it!! I will make a prediction model that should be able to accurately classify and predict the suit of a given image of any arbitrary non-faced playing card.
我相信,要理解任何统计概念,没有什么比一副扑克牌更方便了。 在这里,我将探索一副扑克牌,但形式略有不同寻常。 是的,你猜对了! 我将创建一个预测模型,该模型应该能够准确地分类和预测任意任意非面对式纸牌的给定图像的适合程度。
This dataset contains a set of 43 card images for each suit viz Clubs ♣, Hearts ♥️ , Diamonds ♦️, and Spades ♠️ . Note that the symbols of each suit follow a standard shape however the designing and arrangement of these symbols vary from card to card. We will incorporate this dataset to train and test our model. (To follow the script conveniently, I recommend you to download the images and keep all the files in a parent file as they appear in the Github repository)
该数据集包含每个套装即俱乐部一组43个图像♣,红桃♥️,钻石♦️和黑桃♠️。 请注意,每套西装的符号遵循标准形状,但是这些符号的设计和排列因卡而异。 我们将合并此数据集以训练和测试我们的模型。 (为了方便地遵循脚本,建议您下载图像并将所有文件保存在父文件中,就像它们在Github存储库中显示的一样)
For this task, you would require Keras and EBImage packages. The former is available on the cran repository. The later is used to deal with the images efficiently and can be called from an open-source software called Bioconductor. These can be installed on Windows OS as:
对于此任务,您将需要Keras和EBImage软件包。 前者可在cran信息库中找到。 后者用于有效处理图像,可以从名为Bioconductor的开源软件中调用。 这些可以通过以下方式安装在Windows操作系统上:
install.packages(“keras”) # Install the package from CRANlibrary(keras)install_keras() #to setup the Keras library and TensorFlow backendif (!requireNamespace(“BiocManager”, quietly = TRUE))install.packages(“BiocManager”)BiocManager::install(“EBImage”)library(EBImage)This installs the CPU version of Keras API, which is recommended for the novice for now.
这将安装Keras API的CPU版本,目前推荐新手使用。
Note: The Keras API will require Python support and R tools plug-in. So make sure you have anaconda and R tools installed on your machine with properly added to your system path.
注意: Keras API将需要Python支持和R工具插件。 因此,请确保已在计算机上安装了anaconda和R工具,并将其正确添加到系统路径中。
Next, we will convert the images of each suit into a tensor (numbered matrix). readImage() function from EBImage library does this robustly. Let’s try reading an image from our dataset.
接下来,我们将每个西装的图像转换为张量(编号矩阵)。 EBImage库中的readImage()函数功能强大。 让我们尝试从数据集中读取图像。
setwd(“C:/parent/spade”) # To access the images of Spades suit. # The path should be modified as per your # machinecard<-readImage(“ace_of_spades (2).png”) # Reading an imgae from the # datasetprint(card) # Print the details of imageThis gives the output as:
输出为:
Image colorMode : Color storage.mode : double dim : 500 726 4 frames.total : 4 frames.render: 1imageData(object)[1:5,1:6,1][,1] [,2] [,3] [,4] [,5] [,6][1,] 1 1 1 1 1 1[2,] 1 1 1 1 1 1[3,] 1 1 1 1 1 1[4,] 1 1 1 1 1 1[5,] 1 1 1 1 1 1This indicates that the image is colored with dimension 500 X 726 X 4. Notice, as we have discussed earlier, here the image depth is 4 and so we will need a filter of depth 4. To unmask these four matrixes we use:
这表示图像的尺寸为500 X 726 X4。请注意,如前所述,此处的图像深度为4,因此我们需要一个深度为4的过滤器。要对这四个矩阵进行屏蔽,请使用:
getFrames(card, type=”total”)This will give the details of the four channels separately.
这将分别给出四个通道的详细信息。
[[1]]Image colorMode : Grayscale storage.mode : double dim : 500 726 frames.total : 1 frames.render: 1imageData(object)[1:5,1:6][,1] [,2] [,3] [,4] [,5] [,6][1,] 1 1 1 1 1 1[2,] 1 1 1 1 1 1[3,] 1 1 1 1 1 1[4,] 1 1 1 1 1 1[5,] 1 1 1 1 1 1[[2]]Image colorMode : Grayscale storage.mode : double dim : 500 726 frames.total : 1 frames.render: 1imageData(object)[1:5,1:6][,1] [,2] [,3] [,4] [,5] [,6][1,] 1 1 1 1 1 1[2,] 1 1 1 1 1 1[3,] 1 1 1 1 1 1[4,] 1 1 1 1 1 1[5,] 1 1 1 1 1 1[[3]]Image colorMode : Grayscale storage.mode : double dim : 500 726 frames.total : 1 frames.render: 1imageData(object)[1:5,1:6][,1] [,2] [,3] [,4] [,5] [,6][1,] 1 1 1 1 1 1[2,] 1 1 1 1 1 1[3,] 1 1 1 1 1 1[4,] 1 1 1 1 1 1[5,] 1 1 1 1 1 1[[4]]Image colorMode : Grayscale storage.mode : double dim : 500 726 frames.total : 1 frames.render: 1imageData(object)[1:5,1:6][,1] [,2] [,3] [,4] [,5] [,6][1,] 0 0 0 0 0 0[2,] 0 0 0 0 0 0[3,] 0 0 0 0 0 0[4,] 0 0 0 0 0 0[5,] 0 0 0 0 0 0And oh yeah! to elucidate our selected card we do:
哦,是的! 为了阐明我们选择的卡,我们执行以下操作:
Image by author) 作者提供的图像) display(card)Although the depth is the same for each card in the data set, the pixel dimensions are varying and so we have to resize each of the cards to 100x100x4 dimensions and combine them all in a stack that is compatible to Keras. This stack then directly goes into the architecture as input.
尽管数据集中每张卡的深度都相同,但是像素尺寸是变化的,因此我们必须将每张卡的大小调整为100x100x4尺寸,并将它们全部组合到与Keras兼容的堆栈中。 然后,该堆栈直接作为输入进入体系结构。
setwd(“C:/parent/club”) # To access the images of Clubs suit. # The path should be modified as per your # machineimg.card<- sample(dir()); #-------shuffle the ordercards<-list(NULL); for(i in 1:length(img.card)){ cards[[i]]<- readImage(img.card[i]) cards[[i]]<- resize(cards[[i]], 100, 100)} #resizing to 100x100club<- cards # Storing stack of the Clubs cards in # matrix form in a list#-----------------------------------------------------------setwd(“C:/parent/heart”)# To access the images of Hearts suit. # The path should be modified as per your # machineimg.card<- sample(dir());cards<-list(NULL);for(i in 1:length(img.card)) { cards[[i]]<- readImage(img.card[i])cards[[i]]<- resize(cards[[i]], 100, 100)} #resizing to 100x100heart<- cards # Storing stack of the Hearts cards in # matrix form in a list#------------------------------------------------------------setwd(“C:/parent/spade”)# To access the images of Spades suit. # The path should be modified as per your # machineimg.card<- sample(dir());cards<-list(NULL);for(i in 1:length(img.card)){ cards[[i]]<- readImage(img.card[i])cards[[i]]<- resize(cards[[i]], 100, 100)} #resizing to 100x100spade<- cards # Storing stack of the Spades cards in # matrix form in a list#------------------------------------------------------------setwd(“C:/parent/diamond”) # To access the images of Diamonds suit. #The path should be modified as per your # machineimg.card<- sample(dir());cards<-list(NULL);for(i in 1:length(img.card)){ cards[[i]]<- readImage(img.card[i])cards[[i]]<- resize(cards[[i]], 100, 100)} #resizing to 100x100diamond<- cards # Storing stack of the Diamonds cards in # matrix form in a list#-------------------------------------------------------------train_pool<-c(club[1:40], heart[1:40], spade[1:40], diamond[1:40]) # Vector of all the training images. # The first 40 images from each suit # are included in the train settrain<-aperm(combine(train_pool), c(4,1,2,3)) # Combine and stackedtest_pool<-c(club[41:43], heart[41:43], spade[41:43], diamond[41:43]) # Vector of all test images. The last # 3 images from each suit is included # in test settest<-aperm(combine(test_pool), c(4,1,2,3)) # Combined and stackedTo see what images are included in the test set, we do this:
要查看测试集中包含哪些图像,我们执行以下操作:
par(mfrow=c(3,4)) # To contain all images in single framefor(i in 1:12){ plot(test_pool[[i]]) }par(mfrow=c(1,1)) # Reset the default Image by author) 作者提供的图像)I got the cards as shown in figure 8. It could be a different set of cards for you.
我得到了如图8所示的卡片。它可能对您来说是另一套卡片。
One Hot encoding is necessary to create the categorical vectors corresponding to the input data.
必须进行一种热编码才能创建与输入数据相对应的分类向量。
#one hot encodingtrain_y<-c(rep(0,40),rep(1,40),rep(2,40),rep(3,40))test_y<-c(rep(0,3),rep(1,3),rep(2,3),rep(3,3))train_lab<-to_categorical(train_y) #Catagorical vector for training #classestest_lab<-to_categorical(test_y)#Catagorical vector for test classesBelow is the R script to build the CNN model. I am also giving a comprehensive animation along with it that illustrates what’s what as the script proceeds (Figure 9).
以下是用于构建CNN模型的R脚本。 我还提供了一个综合的动画,它说明了脚本进行过程的内容(图9)。
# Model Buildingmodel.card<- keras_model_sequential() #-Keras Model composed of a #-----linear stack of layersmodel.card %>% #---------Initiate and connect to #----------------------------(A)-----------------------------------#layer_conv_2d(filters = 40, #----------First convoluted layer kernel_size = c(4,4), #---40 Filters with dimension 4x4 activation = ‘relu’, #-with a ReLu activation function input_shape = c(100,100,4)) %>% #----------------------------(B)-----------------------------------#layer_conv_2d(filters = 40, #---------Second convoluted layer kernel_size = c(4,4), #---40 Filters with dimension 4x4 activation = ‘relu’) %>% #-with a ReLu activation function#---------------------------(C)-----------------------------------#layer_max_pooling_2d(pool_size = c(4,4) )%>% #--------Max Pooling#-----------------------------------------------------------------#layer_dropout(rate = 0.25) %>% #-------------------Drop out layer#----------------------------(D)-----------------------------------#layer_conv_2d(filters = 80, #-----------Third convoluted layer kernel_size = c(4,4), #----80 Filters with dimension 4x4 activation = ‘relu’) %>% #--with a ReLu activation function#-----------------------------(E)----------------------------------#layer_conv_2d(filters = 80, #----------Fourth convoluted layer kernel_size = c(4,4), #----80 Filters with dimension 4x4 activation = ‘relu’) %>% #--with a ReLu activation function#-----------------------------(F)----------------------------------#layer_max_pooling_2d(pool_size = c(4,4)) %>% #---------Max Pooling#-----------------------------------------------------------------#layer_dropout(rate = 0.35) %>% #-------------------Drop out layer#------------------------------(G)---------------------------------#layer_flatten()%>% #---Flattening the final stack of feature maps#------------------------------(H)---------------------------------#layer_dense(units = 256, activation = ‘relu’)%>% #-----Hidden layer#---------------------------(I)-----------------------------------#layer_dropout(rate= 0.25)%>% #-------------------Drop-out layer#-----------------------------------------------------------------#layer_dense(units = 4, activation = “softmax”)%>% #-----Final Layer#----------------------------(J)-----------------------------------#compile(loss = 'categorical_crossentropy', optimizer = optimizer_adam(), metrics = c("accuracy")) # Compiling the architecture (Image by author) (作者提供的图片)We can get a summary of this model using summary(model.card). The output of this will be a neat and concise summary of the model.
我们可以使用summary(model.card)获得此模型的摘要。 这样的输出将是模型的简洁明了的摘要。
Model: “sequential”____________________________________________________________________Layer (type) Output Shape Param # ====================================================================conv2d (Conv2D) (None, 97, 97, 40) 2600 ____________________________________________________________________conv2d_1 (Conv2D) (None, 94, 94, 40) 25640 ____________________________________________________________________max_pooling2d (MaxPooling2D) (None, 23, 23, 40) 0 ____________________________________________________________________dropout (Dropout) (None, 23, 23, 40) 0 ____________________________________________________________________conv2d_2 (Conv2D) (None, 20, 20, 80) 51280 ____________________________________________________________________conv2d_3 (Conv2D) (None, 17, 17, 80) 102480 ____________________________________________________________________max_pooling2d_1 (MaxPooling2D) (None, 4, 4, 80) 0 ____________________________________________________________________dropout_1 (Dropout) (None, 4, 4, 80) 0____________________________________________________________________flatten (Flatten) (None, 1280) 0 ____________________________________________________________________dense (Dense) (None, 256) 327936 ____________________________________________________________________dropout_2 (Dropout) (None, 256) 0 ____________________________________________________________________dense_1 (Dense) (None, 4) 1028 ====================================================================Total params: 510,964Trainable params: 510,964Non-trainable params: 0____________________________________________________________________Once the architecture is built, its time to fit our dataset for the training of the model. The fitting is done as:
构建完架构后,就可以调整我们的数据集来训练模型了。 拟合过程如下:
#fit modelhistory<- model.card %>% fit(train, train_lab, epochs = 100, batch_size = 40, validation_split = 0.2 ) Image by author) 作者提供的图像)On fitting, each epoch (forward feed-backpropagation) will appear in the console area. The processing time may vary from machine to machine. While the epochs are running you should see a graphic in the Rstudio viewer (Figure 9). These are the juxtaposed curves of loss and accuracy for training and validation sets.
拟合时,每个时期(前向反馈传播)将出现在控制台区域中。 机器的处理时间可能会有所不同。 在这些时期运行时,您应该在Rstudio查看器中看到一个图形(图9)。 这些是训练和验证集的损失和准确性的并列曲线。
The running epochs appearing in the console looks something like this:
出现在控制台中的运行纪元如下所示:
Train on 128 samples, validate on 32 samplesEpoch 1/100128/128 [==============================] — 10s 78ms/sample — loss: 1.3648 — accuracy: 0.3281 — val_loss: 2.0009 — val_accuracy: 0.0000e+00Epoch 2/100128/128 [==============================] — 8s 59ms/sample — loss: 1.3098 — accuracy: 0.3359 — val_loss: 1.9864 — val_accuracy: 0.0000e+00Epoch 3/100128/128 [==============================] — 8s 61ms/sample — loss: 1.2686 — accuracy: 0.3516 — val_loss: 2.5289 — val_accuracy: 0.0000e+00A summary of the whole training process can be plotted using plot(history).
可以使用plot(history)绘制整个训练过程的摘要。
Once the training is completed. Its time to evaluate our freshly trained model. First, we will look at the performance of moel over the trained data set, and then we will finally test and evaluate our trained model over our test set.
培训完成后。 是时候评估我们新近训练的模型了。 首先,我们将研究经过训练的数据集上的驼峰性能,然后我们将最终根据测试集测试和评估经过训练的模型。
#Model Evaluationmodel.card %>% evaluate(train,train_lab) #Evaluation of training set pred<- model.card %>% predict_classes(train) #-----ClassificationTrain_Result<-table(Predicted = pred, Actual = train_y) #----Resultsmodel.card %>% evaluate(test, test_lab) #-----Evaluation of test setpred1<- model.card %>% predict_classes(test) #-----ClassificationTest_Result<-table(Predicted = pred1, Actual = test_y) #-----Resultsrownames(Train_Result)<-rownames(Test_Result)<-colnames(Train_Result)<-colnames(Test_Result)<-c("Clubs", "Hearts", "Spades", "Diamonds")print(Train_Result)print(Test_Result)This will spit:
这将吐出:
Image by author) 作者提供的图片)The 100% accuracy over the train set can be a sign of overfitting but notice that our model has achieved a 100% accuracy over the test set as well. That means we have successfully made a convolution neural network model to correctly classify a given card image into its true suit.
训练集上的100%精度可能是过拟合的迹象,但请注意,我们的模型也达到了测试集上100%的精度。 这意味着我们已经成功地建立了卷积神经网络模型,以正确地将给定的卡片图像分类为真实的卡片。
If you are here then congratulations!! You have successfully made your Convolution neural network model. Hope you enjoyed the ride. Please feel free to reach out to me in case you find anything fallible or incorrect. I am also open to all suggestions that can improve the quality of this document.
如果您在这里,那就恭喜!! 您已经成功建立了卷积神经网络模型。 希望您喜欢这个旅程。 如果发现任何容易出错或不正确的地方,请随时与我联系。 我也欢迎所有可以提高本文档质量的建议。
Thank you for reading and Happy R-ing 😀
感谢您的阅读和快乐Ring-
Where Is Artificial Intelligence Used: Areas Where AI Can Be Used
在哪里使用人工智能:可以使用AI的区域
Illustrated: 10 CNN Architectures
图解:10种CNN架构
Gentle Dive into Math Behind Convolutional Neural Networks
深入研究卷积神经网络背后的数学
A Comprehensive Guide to Convolutional Neural Networks — the ELI5 way
卷积神经网络综合指南-ELI5方法
Keras for R
Keras为R
Introduction to EBImage
EBImage简介
翻译自: https://towardsdatascience.com/a-laymans-guide-to-building-your-first-image-classification-model-in-r-using-keras-b285deac6572
keras图像分类模型
相关资源:jdk-8u281-windows-x64.exe