人工神经网络 (ANN,Artificial Neural Network)采取的实现方法是将任务分派给许多神经元(也称为节点),且每一个神经元都能够“近似”生成输入函数。所谓的“近似”是指用一个比较简单的函数去表示一个更复杂的函数。此外,如果神经元能够以一定精度近似非线性函数,该网络通常可认为是神经网络。

1. 神经元与感知机

感知机的概念可以追溯到20世纪50年代,感知机是一个可接受许多输入并输出一个值的函数。

每个输入都有一个与之相关联的权重,用来表示函数中输入的重要特性。如,Sigmoid函数:

Sigmoid函数用来指示该函数输出的值为0或1,判断条件是一个阈值,如果输入的权重和大于某一个阈值,感知器会输出1,否则为0。

2. 人工神经网络

如图所示,神经网络有三个不同的层:输入层、隐藏层(或中间层)和输出层。通常一个隐藏层就能够解决现实生活中的大部分问题。

(1)输入层

输入层定义了网络的输入数目。例如,创建一个人工神经网络,使其根据给定的动物属性描述来判断是哪种动物。这些动物属性分别为体重、长度和牙齿。因此,对应这三个属性,网络就需要三个输入节点。

(2)输出层

输出层数据与定义的类别数相同。比如,用来进行动物分类的网络,若已知要分类的动物为狗、秃鹰、海豚和龙,则任意设定输出层的数目为4;如果输入的动物非这些类别,则网络将返回与这4种动物最相似的类别。

(3)隐藏层

隐藏层包含感知器,如前所述,大部分问题只需要一个隐藏层。如何确定隐藏层的神经元数?在实际应用中,并没有严格准则,通常使用经验方法。

3. 创建ANN

创建ANN最常见的规则:

(1)隐藏层神经元数应该介于输入层的大小与输出层大小之间。根据经验,如果输入层大小与输出层的大小相差很大,则隐藏层的神经元数目最好与输出层数接近。

(2)对于相对较小的输入层,隐藏层神经元数最好是输入层和输出层大小之和的三分之二,或者小于输入层大小的两倍。

除此之外,需要注意一个重要现象:过拟合(overfitting)。当待分类训练数据提供的信息没有什么意义,而隐藏层又含有太多信息时就会发生过拟合。

(1)程序示例:

import cv2
import numpy as np
from random import randint

#通过调用OpenCV函数创建ANN
animals_net = cv2.ml.ANN_MLP_create()

#ANN_MLP_RPROP和ANN_MLP_BACKPROP都是反向传播算法,此处设置相应的拓扑结构
animals_net.setLayerSizes(np.array([3, 6, 4]))
animals_net.setTrainMethod(cv2.ml.ANN_MLP_RPROP | cv2.ml.ANN_MLP_UPDATE_WEIGHTS)
animals_net.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM)

#指定ANN的终止条件
animals_net.setTermCriteria(( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 ))

"""Input arrays
weight, length, teeth
"""

"""Output arrays
dog, eagle, dolphin and dragon
"""

def dog_sample():
  return [randint(10, 20), 1, randint(38, 42)]

def dog_class():
  return [1, 0, 0, 0]

def condor_sample():
  return [randint(3,10), randint(3,5), 0]

def condor_class():
  return [0, 1, 0, 0]

def dolphin_sample():
  return [randint(30, 190), randint(5, 15), randint(80, 100)]

def dolphin_class():
  return [0, 0, 1, 0]

def dragon_sample():
  return [randint(1200, 1800), randint(30, 40), randint(160, 180)]

def dragon_class():
  return [0, 0, 0, 1]

def record(sample, classification):
  return (np.array([sample], dtype=np.float32), np.array([classification], dtype=np.float32))

'''
为了提高精度,大多数ANN会迭代多个周期;一些常见的ANN示例,会对数据进行数百次迭代。
'''  
records = []

RECORDS = 5000
for x in range(0, RECORDS):
  records.append(record(dog_sample(), dog_class()))
  records.append(record(condor_sample(), condor_class()))
  records.append(record(dolphin_sample(), dolphin_class()))
  records.append(record(dragon_sample(), dragon_class()))

EPOCHS = 2
for e in range(0, EPOCHS):
  print ("Epoch %d:" % e)
  for t, c in records:
    animals_net.train(t, cv2.ml.ROW_SAMPLE, c)


TESTS = 100
dog_results = 0
for x in range(0, TESTS):
  clas = int(animals_net.predict(np.array([dog_sample()], dtype=np.float32))[0])
  print ("class: %d" % clas)
  if (clas) == 0:
    dog_results += 1

condor_results = 0
for x in range(0, TESTS):
  clas = int(animals_net.predict(np.array([condor_sample()], dtype=np.float32))[0])
  print ("class: %d" % clas)
  if (clas) == 1:
    condor_results += 1

dolphin_results = 0
for x in range(0, TESTS):
  clas = int(animals_net.predict(np.array([dolphin_sample()], dtype=np.float32))[0])
  print ("class: %d" % clas)
  if (clas) == 2:
    dolphin_results += 1

dragon_results = 0
for x in range(0, TESTS):
  clas = int(animals_net.predict(np.array([dragon_sample()], dtype=np.float32))[0])
  print ("class: %d" % clas)
  if (clas) == 3:
    dragon_results += 1

print ("Dog accuracy: %f%%" % (dog_results))
print ("condor accuracy: %f%%" % (condor_results))
print ("dolphin accuracy: %f%%" % (dolphin_results))
print ("dragon accuracy: %f%%" % (dragon_results))

(2)运行结果:

下一篇:《OpenCV3-Python下ANN进行MNIST数字识别》

注意:本站所有文章除特别说明外,均为原创,转载请务必以超链接方式并注明作者出处。 标签:opencv3,图像处理,python