利用卷积神经网络实现四种天气数据集的分类
import torch
import os
import shutil
import torch. optim as optim
import torch. nn as nn
import torch. nn. functional as F
import torchvision
base_dir = r'./4wheather'
if not os. path. isdir( base_dir) :
os. mkdir( base_dir)
train_dir = os. path. join( base_dir, 'train' )
test_dir = os. path. join( base_dir, 'test' )
os. mkdir( train_dir)
os. mkdir( test_dir)
species = [ 'cloudy' , 'rain' , 'shine' , 'sunrise' ]
for train_or_test in [ 'train' , 'test' ] :
for spec in species:
os. mkdir( os. path. join( base_dir, train_or_test, spec) )
image_dir = r'./dataset2'
for i, img in enumerate ( os. listdir( image_dir) ) :
for spec in species:
if spec in img:
s = os. path. join( image_dir, img)
if i% 5 == 0 :
d = os. path. join( base_dir, 'test' , spec, img)
else :
d = os. path. join( base_dir, 'train' , spec, img)
shutil. copy( s, d)
from torchvision import transforms
transform = transforms. Compose( [
transforms. Resize( ( 96 , 96 ) ) ,
transforms. ToTensor( ) ,
transforms. Normalize( mean= [ .5 , .5 , .5 ] ,
std= [ .5 , .5 , .5 ] )
] )
train_ds = torchvision. datasets. ImageFolder( train_dir, transform= transform)
test_ds = torchvision. datasets. ImageFolder( test_dir, transform= transform)
train_dl = torch. utils. data. DataLoader( train_ds, batch_size= 64 , shuffle= True )
test_dl = torch. utils. data. DataLoader( test_ds, batch_size= 64 )
class Net ( nn. Module) :
def __init__ ( self) :
super ( Net, self) . __init__( )
self. conv1 = nn. Conv2d( 3 , 16 , 3 )
self. conv2 = nn. Conv2d( 16 , 32 , 3 )
self. conv3 = nn. Conv2d( 32 , 64 , 3 )
self. pool = nn. MaxPool2d( 2 , 2 )
self. fc1 = nn. Linear( 64 * 10 * 10 , 1024 )
self. fc2 = nn. Linear( 1024 , 4 )
def forward ( self, x) :
x = F. relu( self. conv1( x) )
x = self. pool( x)
x = F. relu( self. conv2( x) )
x = self. pool( x)
x = F. relu( self. conv3( x) )
x = self. pool( x)
x = x. view( - 1 , x. size( 1 ) * x. size( 2 ) * x. size( 3 ) )
x = F. relu( self. fc1( x) )
x = self. fc2( x)
return x
model = Net( )
if torch. cuda. is_available( ) :
model. to( 'cuda' )
loss_fn = nn. CrossEntropyLoss( )
optim = torch. optim. Adam( model. parameters( ) , lr = 0.001 )
def fit ( epoch, model, trainloader, testloader) :
correct = 0
total = 0
running_loss = 0
for x, y in trainloader:
if torch. cuda. is_available( ) :
x, y = x. to( 'cuda' ) , y. to( 'cuda' )
y_pred = model( x)
loss = loss_fn( y_pred, y)
optim. zero_grad( )
loss. backward( )
optim. step( )
with torch. no_grad( ) :
y_pred = torch. argmax( y_pred, dim= 1 )
correct += ( y_pred == y) . sum ( ) . item( )
total += y. size( 0 )
running_loss += loss. item( )
epoch_loss = running_loss / len ( trainloader)
epoch_acc = correct / total
test_correct = 0
test_total = 0
test_running_loss = 0
with torch. no_grad( ) :
for x, y in testloader:
if torch. cuda. is_available( ) :
x, y = x. to( 'cuda' ) , y. to( 'cuda' )
y_pred = model( x)
loss = loss_fn( y_pred, y)
y_pred = torch. argmax( y_pred, dim= 1 )
test_correct += ( y_pred == y) . sum ( ) . item( )
test_total += y. size( 0 )
test_running_loss += loss. item( )
epoch_test_loss = test_running_loss / len ( testloader)
epoch_test_acc = test_correct / test_total
print ( 'epoch: ' , epoch,
'loss: ' , round ( epoch_loss, 3 ) ,
'accuracy:' , round ( epoch_acc, 3 ) ,
'test_loss: ' , round ( epoch_test_loss, 3 ) ,
'test_accuracy:' , round ( epoch_test_acc, 3 )
)
return epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc
epoches = 30
train_loss = [ ]
train_acc = [ ]
test_loss = [ ]
test_acc = [ ]
for epoch in range ( epoches) :
epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc = fit( epoch, model, train_dl, test_dl)
train_loss. append( epoch_loss)
train_acc. append( epoch_acc)
test_loss. append( epoch_test_loss)
test_acc. append( epoch_test_acc)