时间:2021-05-22
需求
在4*4的图片中,比较外围黑色像素点和内圈黑色像素点个数的大小将图片分类
如上图图片外围黑色像素点5个大于内圈黑色像素点1个分为0类反之1类
想法
代码
import torchimport torchvisionimport torchvision.transforms as transformsimport numpy as npfrom PIL import Image构造数据集
import csvimport collectionsimport osimport shutildef buildDataset(root,dataType,dataSize): """构造数据集 构造的图片存到root/{dataType}Data 图片地址和标签的csv文件存到 root/{dataType}DataInfo.csv Args: root:str 项目目录 dataType:str 'train'或者‘test' dataNum:int 数据大小 Returns: """ dataInfo = [] dataPath = f'{root}/{dataType}Data' if not os.path.exists(dataPath): os.makedirs(dataPath) else: shutil.rmtree(dataPath) os.mkdir(dataPath) for i in range(dataSize): # 创建0,1 数组 imageArray=np.random.randint(0,2,(4,4)) # 计算0,1数量得到标签 allBlackNum = collections.Counter(imageArray.flatten())[0] innerBlackNum = collections.Counter(imageArray[1:3,1:3].flatten())[0] label = 0 if (allBlackNum-innerBlackNum)>innerBlackNum else 1 # 将图片保存 path = f'{dataPath}/{i}.jpg' dataInfo.append([path,label]) im = Image.fromarray(np.uint8(imageArray*255)) im = im.convert('1') im.save(path) # 将图片地址和标签存入csv文件 filePath = f'{root}/{dataType}DataInfo.csv' with open(filePath, 'w') as f: writer = csv.writer(f) writer.writerows(dataInfo)root=r'/Users/null/Documents/PythonProject/Classifier'构造训练数据集
buildDataset(root,'train',20000)构造测试数据集
buildDataset(root,'test',10000)读取数据集
class MyDataset(torch.utils.data.Dataset): def __init__(self, root, datacsv, transform=None): super(MyDataset, self).__init__() with open(f'{root}/{datacsv}', 'r') as f: imgs = [] # 读取csv信息到imgs列表 for path,label in map(lambda line:line.rstrip().split(','),f): imgs.append((path, int(label))) self.imgs = imgs self.transform = transform if transform is not None else lambda x:x def __getitem__(self, index): path, label = self.imgs[index] img = self.transform(Image.open(path).convert('1')) return img, label def __len__(self): return len(self.imgs)trainData=MyDataset(root = root,datacsv='trainDataInfo.csv', transform=transforms.ToTensor())testData=MyDataset(root = root,datacsv='testDataInfo.csv', transform=transforms.ToTensor())处理数据集使得数据集不偏斜
import itertoolsdef chooseData(dataset,scale): # 将类别为1的排序到前面 dataset.imgs.sort(key=lambda x:x[1],reverse=True) # 获取类别1的数目 ,取scale倍的数组,得数据不那么偏斜 trueNum =collections.Counter(itertools.chain.from_iterable(dataset.imgs))[1] end = min(trueNum*scale,len(dataset)) dataset.imgs=dataset.imgs[:end]scale = 4chooseData(trainData,scale)chooseData(testData,scale)len(trainData),len(testData)(2250, 1122)import torch.utils.data as Data# 超参数batchSize = 50lr = 0.1numEpochs = 20trainIter = Data.DataLoader(dataset=trainData, batch_size=batchSize, shuffle=True)testIter = Data.DataLoader(dataset=testData, batch_size=batchSize)定义模型
from torch import nnfrom torch.autograd import Variablefrom torch.nn import Module,Linear,Sequential,Conv2d,ReLU,ConstantPad2dimport torch.nn.functional as Fclass Net(Module): def __init__(self): super(Net, self).__init__() self.cnnLayers = Sequential( # padding添加1层常数1,设定卷积核为2*2 ConstantPad2d(1, 1), Conv2d(1, 1, kernel_size=2, stride=2,bias=True) ) self.linearLayers = Sequential( Linear(9, 2) ) def forward(self, x): x = self.cnnLayers(x) x = x.view(x.shape[0], -1) x = self.linearLayers(x) return xclass Net2(Module): def __init__(self): super(Net2, self).__init__() self.cnnLayers = Sequential( Conv2d(1, 1, kernel_size=1, stride=1,bias=True) ) self.linearLayers = Sequential( ReLU(), Linear(16, 2) ) def forward(self, x): x = self.cnnLayers(x) x = x.view(x.shape[0], -1) x = self.linearLayers(x) return x定义损失函数
# 交叉熵损失函数loss = nn.CrossEntropyLoss()loss2 = nn.CrossEntropyLoss()定义优化算法
net = Net()optimizer = torch.optim.SGD(net.parameters(),lr = lr)net2 = Net2()optimizer2 = torch.optim.SGD(net2.parameters(),lr = lr)训练模型
# 计算准确率def evaluateAccuracy(dataIter, net): accSum, n = 0.0, 0 with torch.no_grad(): for X, y in dataIter: accSum += (net(X).argmax(dim=1) == y).float().sum().item() n += y.shape[0] return accSum / ndef train(net, trainIter, testIter, loss, numEpochs, batchSize, optimizer): for epoch in range(numEpochs): trainLossSum, trainAccSum, n = 0.0, 0.0, 0 for X,y in trainIter: yHat = net(X) l = loss(yHat,y).sum() optimizer.zero_grad() l.backward() optimizer.step() # 计算训练准确度和loss trainLossSum += l.item() trainAccSum += (yHat.argmax(dim=1) == y).sum().item() n += y.shape[0] # 评估测试准确度 testAcc = evaluateAccuracy(testIter, net) print('epoch {:d}, loss {:.4f}, train acc {:.3f}, test acc {:.3f}'.format(epoch + 1, trainLossSum / n, trainAccSum / n, testAcc))Net模型训练
train(net, trainIter, testIter, loss, numEpochs, batchSize,optimizer)epoch 1, loss 0.0128, train acc 0.667, test acc 0.667epoch 2, loss 0.0118, train acc 0.683, test acc 0.760epoch 3, loss 0.0104, train acc 0.742, test acc 0.807epoch 4, loss 0.0093, train acc 0.769, test acc 0.772epoch 5, loss 0.0085, train acc 0.797, test acc 0.745epoch 6, loss 0.0084, train acc 0.798, test acc 0.807epoch 7, loss 0.0082, train acc 0.804, test acc 0.816epoch 8, loss 0.0078, train acc 0.816, test acc 0.812epoch 9, loss 0.0077, train acc 0.818, test acc 0.817epoch 10, loss 0.0074, train acc 0.824, test acc 0.826epoch 11, loss 0.0072, train acc 0.836, test acc 0.819epoch 12, loss 0.0075, train acc 0.823, test acc 0.829epoch 13, loss 0.0071, train acc 0.839, test acc 0.797epoch 14, loss 0.0067, train acc 0.849, test acc 0.824epoch 15, loss 0.0069, train acc 0.848, test acc 0.843epoch 16, loss 0.0064, train acc 0.864, test acc 0.851epoch 17, loss 0.0062, train acc 0.867, test acc 0.780epoch 18, loss 0.0060, train acc 0.871, test acc 0.864epoch 19, loss 0.0057, train acc 0.881, test acc 0.890epoch 20, loss 0.0055, train acc 0.885, test acc 0.897Net2模型训练
# batchSize = 50 # lr = 0.1# numEpochs = 15 下得出的结果train(net2, trainIter, testIter, loss2, numEpochs, batchSize,optimizer2)epoch 1, loss 0.0119, train acc 0.638, test acc 0.676epoch 2, loss 0.0079, train acc 0.823, test acc 0.986epoch 3, loss 0.0046, train acc 0.987, test acc 0.977epoch 4, loss 0.0030, train acc 0.983, test acc 0.973epoch 5, loss 0.0023, train acc 0.981, test acc 0.976epoch 6, loss 0.0019, train acc 0.980, test acc 0.988epoch 7, loss 0.0016, train acc 0.984, test acc 0.984epoch 8, loss 0.0014, train acc 0.985, test acc 0.986epoch 9, loss 0.0013, train acc 0.987, test acc 0.992epoch 10, loss 0.0011, train acc 0.989, test acc 0.993epoch 11, loss 0.0010, train acc 0.989, test acc 0.996epoch 12, loss 0.0010, train acc 0.992, test acc 0.994epoch 13, loss 0.0009, train acc 0.993, test acc 0.994epoch 14, loss 0.0008, train acc 0.995, test acc 0.996epoch 15, loss 0.0008, train acc 0.994, test acc 0.998测试
test = torch.Tensor([[[[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]]], [[[1,1,1,1],[1,0,0,1],[1,0,0,1],[1,1,1,1]]], [[[0,1,0,1],[1,0,0,1],[1,0,0,1],[0,0,0,1]]], [[[0,1,1,1],[1,0,0,1],[1,0,0,1],[0,0,0,1]]], [[[0,0,1,1],[1,0,0,1],[1,0,0,1],[1,0,1,0]]], [[[0,0,1,0],[0,1,0,1],[0,0,1,1],[1,0,1,0]]], [[[1,1,1,0],[1,0,0,1],[1,0,1,1],[1,0,1,1]]] ])target=torch.Tensor([0,1,0,1,1,0,1])testtensor([[[[0., 0., 0., 0.], [0., 1., 1., 0.], [0., 1., 1., 0.], [0., 0., 0., 0.]]], [[[1., 1., 1., 1.], [1., 0., 0., 1.], [1., 0., 0., 1.], [1., 1., 1., 1.]]], [[[0., 1., 0., 1.], [1., 0., 0., 1.], [1., 0., 0., 1.], [0., 0., 0., 1.]]], [[[0., 1., 1., 1.], [1., 0., 0., 1.], [1., 0., 0., 1.], [0., 0., 0., 1.]]], [[[0., 0., 1., 1.], [1., 0., 0., 1.], [1., 0., 0., 1.], [1., 0., 1., 0.]]], [[[0., 0., 1., 0.], [0., 1., 0., 1.], [0., 0., 1., 1.], [1., 0., 1., 0.]]], [[[1., 1., 1., 0.], [1., 0., 0., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.]]]])with torch.no_grad(): output = net(test) output2 = net2(test)predictions =output.argmax(dim=1)predictions2 =output2.argmax(dim=1)# 比较结果print(f'Net测试结果{predictions.eq(target)}')print(f'Net2测试结果{predictions2.eq(target)}')Net测试结果tensor([ True, True, False, True, True, True, True])Net2测试结果tensor([False, True, False, True, True, False, True])到此这篇关于Pytorch 使用CNN图像分类的实现的文章就介绍到这了,更多相关Pytorch CNN图像分类内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
今天,我结合代码来详细介绍如何使用SciSharpSTACK的TensorFlow.NET来训练CNN模型,该模型主要实现图像的分类,可以直接移植该代码在CPU
听说pytorch使用比TensorFlow简单,加之pytorch现已支持windows,所以今天装了pytorch玩玩,第一件事还是写了个简单的CNN在MN
产生此次实验的原因:当我使用pytorch进行神经网络的训练时,需要每次向CNN传入一组图像,并且这些图片的存放位置是在两个文件夹中:A文件夹:图片1a,图片2
pytorch指定GPU在用pytorch写CNN的时候,发现一运行程序就卡住,然后cpu占用率100%,nvidia-smi查看显卡发现并没有使用GPU。所以
在pytorch的CNN代码中经常会看到x.view(x.size(0),-1)首先,在pytorch中的view()函数就是用来改变tensor的形状的,例如