搭建神经网络实现简单图片分类

数据来源于吴恩达L2HW3(SIGNS 数据集),训练集包含1800张64*64像素的彩色图片,图片内容为手势,表示从0到5的数字,所要做的是搭建较深的神经网络,以实现图片分类。测试集包含120张图片。

数据集读取:

def load_dataset():
    %cd '/content/drive/MyDrive/Colab Notebooks/吴恩达L2HW3/dataset'
    train_dataset = h5py.File('train_signs.h5', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels

    test_dataset = h5py.File('test_signs.h5', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels

    classes = np.array(test_dataset["list_classes"][:]) # the list of classes
    
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
    
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
X_train_orig , Y_train_orig , X_test_orig , Y_test_orig , classes = load_dataset()
index = 12
plt.imshow(X_train_orig[index])
plt.show()
print(X_train_orig.shape)#1080张图片,64*64*3
Y_train_orig.shape

 

 数据预处理 :

train.sign.h5文件包含的是训练集,train_set_x为64*64*3*1800的tensor,1800为样本数,train_set_y为所对应的类别,维度为6*1080,需要首先每一样本数据进行归一化(/255),之后进行flatten才可输入模型,flatten之后的维度为(122280,1800)(X_train)

X_train_flatten=X_train_orig.reshape(X_train_orig.shape[0], -1).T
X_train_flatten.shape#每一列代表一个样本
X_test_flatten = X_test_orig.reshape(X_test_orig.shape[0], -1).T
#归一化
X_train_flatten=X_train_flatten/255
X_test_flatten=X_test_flatten/255

对训练集进行随机划分(Mini-Batch):

def random_mini_batches(X,Y,mini_batch_size,seed):
    m=X.shape[1]
    mini_batches=[]
    np.random.seed(seed)
    permutation=list(np.random.permutation(m))
    shuffled_X=X[:,permutation]
    shuffled_Y=Y[:,permutation]
    num_complete_minibatches=math.floor(m/mini_batch_size)
    for k in range(num_complete_minibatches):
      mini_batch_X=shuffled_X[:,k*mini_batch_size:(k+1)*mini_batch_size]
      mini_batch_Y=shuffled_Y[:,k*mini_batch_size:(k+1)*mini_batch_size]
      mini_batch=(mini_batch_X,mini_batch_Y)
      mini_batches.append(mini_batch)
    if m % mini_batch_size != 0:
      mini_batch_X = shuffled_X[:,num_complete_minibatches*mini_batch_size:m]
      mini_batch_Y = shuffled_Y[:,num_complete_minibatches*mini_batch_size:m]
      mini_batch = (mini_batch_X,mini_batch_Y)
      mini_batches.append(mini_batch)
    return mini_batches

shuffle:如下所示,创建训练集(X,Y)的随机打乱版本。X和Y中的每一列代表一个训练示例。随机打乱是在X和Y之间同步完成的。 

 

Partition:将打乱后的(X,Y)划分为大小为mini_batch_size(此处为32)的小批处理。训练示例的数量并不总是可以被mini_batch_size整除。最后的小批量可能较小。

模型搭建:全连接层-->relu-->全连接层-->relu-->全连接层

class Model(torch.nn.Module):
  def __init__(self,n_x,h1,h2,n_y):
    super(Model,self).__init__()
    self.linear1=torch.nn.Linear(n_x,h1)#(上一层特征数,该层神经元数)
    self.relu1=torch.nn.ReLU()
    self.linear2=torch.nn.Linear(h1,h2)
    self.relu2=torch.nn.ReLU()
    self.linear3=torch.nn.Linear(h2,n_y)
    self.model=torch.nn.Sequential(self.linear1,self.relu1,self.linear2,self.relu2,self.linear3)
  def forward(self,x):
    return self.model(x)

 训练数据输入模型:

m=Model(X_train_flatten.shape[0],25,12,6)#隐藏层神经元数为25,12,6最后一层输出对应类别的概率
num = torch.cuda.device_count()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
X_train_flatten = torch.from_numpy(X_train_flatten).to(torch.float32).to(device)
Y_train = torch.from_numpy(Y_train_orig).to(torch.float32).to(device)
X_test_flatten = torch.from_numpy(X_test_flatten).to(torch.float32).to(device)
Y_test = torch.from_numpy(Y_test_orig).to(torch.float32).to(device)

模型参数的设定:

m.to(device)
epoch_num = 2000
learning_rate = 0.0001
minibatch_size = 32
seed = 3
costs = []
optimizer = torch.optim.Adam(m.model.parameters(), lr=learning_rate)
loss_func = torch.nn.CrossEntropyLoss()

模型训练:

for epoch in range(epoch_num):
  num_minibatches = int(X_train_flatten.shape[1] / minibatch_size)
  minibatches = random_mini_batches(X_train_flatten, Y_train, minibatch_size, seed)
  epoch_cost = 0
  for minibatch in minibatches:
    (minibatch_X, minibatch_Y) = minibatch
    y_pred = m.forward(minibatch_X.T)
    y = minibatch_Y.T
    y = y.view(-1)
    loss = loss_func(y_pred, y.long())
    epoch_cost = epoch_cost + loss.item()#在pytorch里用item取出这个唯一的元素
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
  epoch_cost = epoch_cost / (num_minibatches + 1)
  if epoch % 5 == 0:
    costs.append(epoch_cost)
            # 是否打印:
    if epoch % 100 == 0:
      print("epoch = " + str(epoch) + "    epoch_cost = " + str(epoch_cost))

这里需要注意:计算损失时,我们需要将预测标签值y_pred和实际标签值y传入损失函数中,y_pred的维度为(n,6),而y的维度为(n),交叉熵函数(pytorch)会在内部将y转换为one-hot形式,y的维度会变成(n,6)。而在tensorflow框架中,损失函数不会帮我们完成one-hot的转换,我们要自己完成。 

epoch = 0    epoch_cost = 1.7447822058902067
epoch = 100    epoch_cost = 1.0144566087161793
epoch = 200    epoch_cost = 0.8499525382238275
epoch = 300    epoch_cost = 0.7405223215327543
epoch = 400    epoch_cost = 0.6508408206350663
epoch = 500    epoch_cost = 0.5719360849436592
epoch = 600    epoch_cost = 0.5000492202885011
epoch = 700    epoch_cost = 0.4312421894248794
epoch = 800    epoch_cost = 0.36556195949806886
epoch = 900    epoch_cost = 0.3063356779954013
epoch = 1000    epoch_cost = 0.25039714048890505
epoch = 1100    epoch_cost = 0.19280040614745197
epoch = 1200    epoch_cost = 0.14023028938647578
epoch = 1300    epoch_cost = 0.10207015522481765
epoch = 1400    epoch_cost = 0.11564182287410778
epoch = 1500    epoch_cost = 0.09902713168412447
epoch = 1600    epoch_cost = 0.06645032955224023
epoch = 1700    epoch_cost = 0.045455615638810044
epoch = 1800    epoch_cost = 0.07567436467198764
epoch = 1900    epoch_cost = 0.02966493705068441
#模型保存:
torch.save(m,'/content/drive/MyDrive/Colab Notebooks/吴恩达L2HW3/图片数字分辨.pth')

 测试集上的表现:

y_test_pred=m.forward(X_test_flatten.T)
y = Y_test.T
y = y.view(-1)
loss = loss_func(y_test_pred, y.long())
y_model_pred=[]
for i in range(X_test_flatten.shape[1]):
  y_model_pred.append(torch.argmax(y_test_pred[i],dim=0).item())
for index in range(X_test_flatten.shape[1]):
  plt.imshow(X_test_orig[index])
  plt.show()
  print(y_model_pred[index])

 

0

0

0

0

2

 

 

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值