概述:
本文将通过组织自己的训练数据,使用Pytorch深度学习框架来训练自己的模型,最终实现自己的图像分类!本篇文章以识别阳台为例子,进行讲述。
一. 数据准备
深度学习的基础就是数据,完成图像分类,当然数据也必不可少。先使用爬虫爬取阳台图片1200张以及非阳台图片1200张,图片的名字从0.jpg一直编到2400.jpg,把爬取的图片放置在同一个文件夹中命名为image(如下图1所示)。

图1
百度图片的爬虫代码也被放在上面,方便大家使用,代码可以抓取任何自定义图片:
[En]
The crawler code for Baidu pictures is also put on to facilitate everyone’s use, and the code can crawl any custom image:
import requests
import os
import urllib
class Spider_baidu_image():
def __init__(self):
self.url = 'http://image.baidu.com/search/acjson?'
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\
3497.81 Safari/537.36'}
self.headers_image = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\
3497.81 Safari/537.36',
'Referer': 'http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1557124645631_R&pv=&ic=&nc=1&z=&hd=1&latest=0©right=0&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E8%83%A1%E6%AD%8C'}
self.keyword = input("请输入搜索图片关键字:")
self.paginator = int(input("请输入搜索页数,每页30张图片:"))
def get_param(self):
"""
获取url请求的参数,存入列表并返回
:return:
"""
keyword = urllib.parse.quote(self.keyword)
params = []
for i in range(1, self.paginator + 1):
params.append(
'tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=1&latest=0©right=0&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&cg=star&pn={}&rn=30&gsm=78&1557125391211='.format(
keyword, keyword, 30 * i))
return params
def get_urls(self, params):
"""
由url参数返回各个url拼接后的响应,存入列表并返回
:return:
"""
urls = []
for i in params:
urls.append(self.url + i)
return urls
def get_image_url(self, urls):
image_url = []
for url in urls:
json_data = requests.get(url, headers=self.headers).json()
json_data = json_data.get('data')
for i in json_data:
if i:
image_url.append(i.get('thumbURL'))
return image_url
def get_image(self, image_url):
"""
根据图片url,在本地目录下新建一个以搜索关键字命名的文件夹,然后将每一个图片存入。
:param image_url:
:return:
"""
cwd = os.getcwd()
file_name = os.path.join(cwd, self.keyword)
if not os.path.exists(self.keyword):
os.mkdir(file_name)
for index, url in enumerate(image_url, start=1):
with open(file_name + '\\{}.jpg'.format(index), 'wb') as f:
f.write(requests.get(url, headers=self.headers_image).content)
if index != 0 and index % 30 == 0:
print('{}第{}页下载完成'.format(self.keyword, index / 30))
def __call__(self, *args, **kwargs):
params = self.get_param()
urls = self.get_urls(params)
image_url = self.get_image_url(urls)
self.get_image(image_url)
if __name__ == '__main__':
spider = Spider_baidu_image()
spider()
每个图片要加上对应的标签,那么在txt文档当中,选取图片的名称,在其后加上标签。如果是阳台,则标签为1,如果不是阳台,则标签为0。在2400张图片中,分成两个txt文档为训练集和验证集”train.txt”和”val.txt”(如下图2,3所示)

图2

图3
通过观察自己爬取的图片,可以发现阳台各式各样,有的半开放,有的是封闭式的,有的甚至和其他可识别物体花,草混在一起。同时,图片尺寸也不一致,有的是竖放的长方形,有的是横放的长方形,但我们最终需要是合理尺寸的正方形。所以我们使用Resize的库用于给图像进行缩放操作,我这里把图片缩放到84*84的级别。除缩放操作以外还需对数据进行预处理:
torchvision.transforms是pytorch中的图像预处理包
一般用Compose把多个步骤整合到一起:
比如说
transforms.Compose([
transforms.CenterCrop(84),
transforms.ToTensor(),
])
这样就把两个步骤整合到一起
CenterCrop用于从中心裁剪图片,目标是一个长宽都为84的正方形,方便后续的计算。除CenterCrop外补充一个RandomCrop是在一个随机的位置进行裁剪。
ToTenser()这个函数的目的就是读取图片像素并且转化为0-1的数字(进行归一化操作)。
代码如下:
data_transforms = {
'train': transforms.Compose([
transforms.Resize(84),
transforms.CenterCrop(84),
# 转换成tensor向量
transforms.ToTensor(),
# 对图像进行归一化操作
# [0.485, 0.456, 0.406],RGB通道的均值与标准差
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(84),
transforms.CenterCrop(84),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
解决对图像的处理过后,想要开始训练网络模型,首先要解决的就是图像数据的读入,Pytorch使用DataLoader来实现图像数据读入,代码如下:
class my_Data_Set(nn.Module):
def __init__(self, txt, transform=None, target_transform=None, loader=None):
super(my_Data_Set, self).__init__()
# 打开存储图像名与标签的txt文件
fp = open(txt, 'r')
images = []
labels = []
# 将图像名和图像标签对应存储起来
for line in fp:
line.strip('\n')
line.rstrip()
information = line.split()
images.append(information[0])
labels.append(int(information[1]))
self.images = images
self.labels = labels
self.transform = transform
self.target_transform = target_transform
self.loader = loader
# 重写这个函数用来进行图像数据的读取
def __getitem__(self, item):
# 获取图像名和标签
imageName = self.images[item]
label = self.labels[item]
# 读入图像信息
image = self.loader(imageName)
# 处理图像数据
if self.transform is not None:
image = self.transform(image)
return image, label
# 重写这个函数,来看数据集中含有多少数据
def __len__(self):
return len(self.images)
# 生成Pytorch所需的DataLoader数据输入格式
train_dataset = my_Data_Set('train.txt', transform=data_transforms['train'], loader=Load_Image_Information)
test_dataset = my_Data_Set('val.txt', transform=data_transforms['val'], loader=Load_Image_Information)
train_loader = DataLoader(train_dataset, batch_size=10, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=10, shuffle=True)
可验证是否生成了DataLoader格式数据:
# 验证是否生成DataLoader格式数据
for data in train_loader:
inputs, labels = data
print(inputs)
print(labels)
for data in test_loader:
inputs, labels = data
print(inputs)
print(labels)
二.定义一个卷积神经网络
卷积神经网络一种典型的多层神经网络,擅长处理图像特别是大图像的相关机器学习问题。卷积神经网络通过一系列的方法,成功地将大数据量的图像识别问题不断降维,最终使其能够被训练。卷积神经网络(CNN)最早由Yann LeCun提出并应用在手写体识别上。
一个典型的CNN网络架构如下图4:

图4
首先导入Python需要的库:
import torch
from torch.utils.data import DataLoader
from torchvision import transforms, datasets
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data import Dataset
import numpy as np
import os
from PIL import Image
import warnings
import matplotlib.pyplot as plt
warnings.filterwarnings("ignore")
plt.ion()
定义一个卷积神经网络:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 18 * 18, 800)
self.fc2 = nn.Linear(800, 120)
self.fc3 = nn.Linear(120, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 18 * 18)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
我们首先定义了一个Net类,它封装了所以训练的步骤,包括卷积、池化、激活以及全连接操作。
__init__函数首先定义了所需要的所有函数,这些函数都会在forward中调用。从conv1说起,conv1实际上就是定义一个卷积层,3代表的是输入图像的像素数组的层数,一般来说就是输入的图像的通道数,比如这里使用的图像都是彩色图像,由R、G、B三个通道组成,所以数值为3;6代表的是我们希望进行6次卷积,每一次卷积都能生成不同的特征映射数组,用于提取图像的6种特征。每一个特征映射结果最终都会被堆叠在一起形成一个图像输出,再作为下一步的输入;5就是过滤框架的尺寸,表示我们希望用一个5 *5的矩阵去和图像中相同尺寸的矩阵进行点乘再相加,形成一个值。定义好了卷基层,我们接着定义池化层。池化层所做的事说来简单,其实就是因为大图片生成的像素矩阵实在太大了,我们需要用一个合理的方法在降维的同时又不失去物体特征,所以使用池化的技术,每四个元素合并成一个元素,用这一个元素去代表四个元素的值,所以图像体积会降为原来的四分之一。再往下一行,我们又一次碰见了一个卷基层:conv2,和conv1一样,它的输入也是一个多层像素数组,输出也是一个多层像素数组,不同的是这一次完成的计算量更大了,我们看这里面的参数分别是6,16,5。之所以为6是因为conv1的输出层数为6,所以这里输入的层数就是6;16代表conv2的输出层数,和conv1一样,16代表着这一次卷积操作将会学习图片的16种映射特征,特征越多理论上能学习的效果就越好。conv2使用的过滤框尺寸和conv1一样,所以不再重复。
对于fc1,16很好理解,因为最后一次卷积生成的图像矩阵的高度就是16层,前面我们把训练图像裁剪成一个84 * 84的正方形尺寸,所以图像最早输入就是一个3 * 84 * 84的数组。经过第一次5 5的卷积之后,我们可以得出卷积的结果是一个6 * 80 * 80的矩阵,这里的80就是因为我们使用了一个5 5的过滤框,当它从左上角第一个元素开始卷积后,过滤框的中心是从2到78,并不是从0到79,所以结果就是一个80 * 80的图像了。经过一个池化层之后,图像尺寸的宽和高都分别缩小到原来的1/2,所以变成40 * 40。紧接着又进行了一次卷积,和上一次一样,长宽都减掉4,变成36 * 36,然后应用了最后一层的池化,最终尺寸就是18 * 18。所以第一层全连接层的输入数据的尺寸是16 * 18 * 18。三个全连接层所做的事很类似,就是不断训练,最后输出一个二分类数值。
net类的forward函数表示前向计算的整个过程。forward接受一个input,返回一个网络输出值,中间的过程就是一个调用init函数中定义的层的过程。
F.relu是一个激活函数,把所有的非零值转化成零值。此次图像识别的最后关键一步就是真正的循环训练操作。
#训练
cirterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.5)
for epoch in range(50):
running_loss = 0.0
for i, data in enumerate(train_loader, 0):
inputs, labels = data
inputs, labels = Variable(inputs), Variable(labels)
optimizer.zero_grad() # 优化器清零
outputs = net(inputs)
loss = cirterion(outputs, labels)
loss.backward()
optimizer.step() #优化
running_loss += loss.item()
if i % 200 == 199:
print('[%d %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 200))
running_loss = 0.0
print('finished training!')
在这里我们进行了50次训练,每次训练都是批量获取train_loader中的训练数据、梯度清零、计算输出值、计算误差、反向传播并修正模型。我们以每200次计算的平均误差作为观察值。
下面进行测试环节:
#测试
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
outputs = net(Variable(images))
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Accuracy of the network on the 400 test images: %d %%' % (100 * correct / total))
最后会得到一个识别的准确率。
三.完整代码如下:
import torch
from torch.utils.data import DataLoader
from torchvision import transforms, datasets
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data import Dataset
import numpy as np
import os
from PIL import Image
import warnings
import matplotlib.pyplot as plt
warnings.filterwarnings("ignore")
plt.ion()
data_transforms = {
'train': transforms.Compose([
transforms.Resize(84),
transforms.CenterCrop(84),
# 转换成tensor向量
transforms.ToTensor(),
# 对图像进行归一化操作
# [0.485, 0.456, 0.406],RGB通道的均值与标准差
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(84),
transforms.CenterCrop(84),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
def Load_Image_Information(path):
# 图像存储路径
image_Root_Dir= r'C:/Users/wbl/Desktop/pythonProject1/image/'
# 获取图像的路径
iamge_Dir = os.path.join(image_Root_Dir, path)
# 以RGB格式打开图像
# Pytorch DataLoader就是使用PIL所读取的图像格式
return Image.open(iamge_Dir).convert('RGB')
class my_Data_Set(nn.Module):
def __init__(self, txt, transform=None, target_transform=None, loader=None):
super(my_Data_Set, self).__init__()
# 打开存储图像名与标签的txt文件
fp = open(txt, 'r')
images = []
labels = []
# 将图像名和图像标签对应存储起来
for line in fp:
line.strip('\n')
line.rstrip()
information = line.split()
images.append(information[0])
labels.append(int(information[1]))
self.images = images
self.labels = labels
self.transform = transform
self.target_transform = target_transform
self.loader = loader
# 重写这个函数用来进行图像数据的读取
def __getitem__(self, item):
# 获取图像名和标签
imageName = self.images[item]
label = self.labels[item]
# 读入图像信息
image = self.loader(imageName)
# 处理图像数据
if self.transform is not None:
image = self.transform(image)
return image, label
# 重写这个函数,来看数据集中含有多少数据
def __len__(self):
return len(self.images)
# 生成Pytorch所需的DataLoader数据输入格式
train_dataset = my_Data_Set('train.txt', transform=data_transforms['train'], loader=Load_Image_Information)
test_dataset = my_Data_Set('val.txt', transform=data_transforms['val'], loader=Load_Image_Information)
train_loader = DataLoader(train_dataset, batch_size=10, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=10, shuffle=True)
'''
# 验证是否生成DataLoader格式数据
for data in train_loader:
inputs, labels = data
print(inputs)
print(labels)
for data in test_loader:
inputs, labels = data
print(inputs)
print(labels)
'''
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 18 * 18, 800)
self.fc2 = nn.Linear(800, 120)
self.fc3 = nn.Linear(120, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 18 * 18)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
#训练
cirterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.5)
for epoch in range(50):
running_loss = 0.0
for i, data in enumerate(train_loader, 0):
inputs, labels = data
inputs, labels = Variable(inputs), Variable(labels)
optimizer.zero_grad() # 优化器清零
outputs = net(inputs)
loss = cirterion(outputs, labels)
loss.backward()
optimizer.step() #优化
running_loss += loss.item()
if i % 200 == 199:
print('[%d %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 200))
running_loss = 0.0
print('finished training!')
#测试
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
outputs = net(Variable(images))
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Accuracy of the network on the 400 test images: %d %%' % (100 * correct / total))
欢迎大家批评指正~
Original: https://blog.csdn.net/weixin_52188227/article/details/124511438
Author: @Benron
Title: 使用Pytorch完成图像分类任务
相关阅读
Title: 股票数据可视化
本文通过对股票数据进行可视化数据分析。(tushare ID:452043)
- tushare介绍
- 数据爬取
- 数据可视化分析
3.1. 近三年的走势
3.2. 股票点数的最大值区间
3.3. 每日低点分析
3.4. 高低点分析 - 总结
代码部分
Tushare是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据,为他们在数据获取方面极大地减轻工作量,使他们更加专注于策略和模型的研究与实现上。考虑到Python pandas包在金融量化分析中体现出的优势,Tushare返回的绝大部分的数据格式都是pandas DataFrame类型,非常便于用pandas/NumPy/Matplotlib进行数据分析和可视化。当然,如果您习惯了用Excel或者关系型数据库做分析,您也可以通过Tushare的数据存储功能,将数据全部保存到本地后进行分析。
2.数据爬取
利用python的财经数据包tushare,就直接可以将你想获取的数据下载下来,它也是有接口的,利用不同的接口可以获取不同的数据。
3.数据可视化分析
3.1.近三年的走势

由走势图可知,这只股票还是较为不稳定,在上升过程较为急速,体现为在一定时期内,市场行情好,遂大幅度上涨,而过大的涨幅体现了市场可能出现了一定的泡沫,并且受到行业的影响因素,在下降过程,也较为急速,体现了该股票容易受到市场的波动,但整体仍然呈现上涨趋势。
3.2.股票点数的最大值区间

由图可知,该股票每天的最大值分布最多点数的位置在75-100之间,50-75的点数较多,100以上的点数较少,50以下是最少的。
3.3.每日低点分析
*[En]*
**

*[En]*
**
3.4.高低点分析
我们对该股票的起始值进行分析,判断其低开多还是低开多。

由图可知,该股票稍微高开的时候比较多。
; 4.总结
由上面四个分析可知,恒瑞医药(代码600276)这个股票此时处于较低位置,但由于最近所属行业的影响,暂时处于困境,无法判断是否能够脱离困境以及什么时候脱离困境。
*[En]*
**
代码部分:
import tushare as tsimport pandas as pdstock_data = ts.get_hist_data('600276')stock_data.to_csv(r'stock_data.csv')import numpy as npimport matplotlib.pyplot as pltdf = pd.read_csv(r'stock_data.csv')x = df['date']y = df['close']plt.figure(figsize=(10,10))plt.plot(x, y)plt.title('close-date')plt.xlabel('date')plt.ylabel('close')plt.savefig(r'1.jpg')plt.show()import pandas as pdimport matplotlib.pyplot as pltdf = pd.read_csv(r'stock_data.csv')plt.title('股票运势最高点分布(百分点)')#绘制标题plt.rcParams['font.sans-serif']='SimHei'#设置中文显示label=['50以下','50-75','75-100','100以上']#定义饼图的标签,标签是列表explode=[0.01,0.01,0.01,0.01]#设定各项距离圆心n个半径values=[len(df[df['high']50]),len(df[(df['high'] >50) & (df['high'] 75)]),len(df[(df['high'] >75 ) & (df['high'] 100)]),len(df[df['high'] > 100])]plt.pie(values,explode=explode,labels=label,autopct='%1.1f%%',radius=2)#绘制饼图plt.savefig(r'2.jpg')plt.show()df = pd.read_csv(r'stock_data.csv')x = df['date']y = df['low']plt.figure(figsize=(10,10))plt.title("min-date")plt.xlabel("date")plt.ylabel("min")plt.plot(x,y,"ob")plt.savefig(r'6.jpg')plt.show()import numpy as npimport matplotlib.pyplot as pltimport pandas as pddf = pd.read_csv(r'stock_data.csv')plt.savefig(r'8.jpg')df.hist('open')plt.show()
Original: https://blog.csdn.net/hk554775/article/details/122626861
Author: 小菜鸟的成长之旅
Title: 股票数据可视化
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/220249/
转载文章受原作者版权保护。转载请注明原作者出处!