commit
352280f95e
|
@ -0,0 +1,196 @@
|
|||
# Dogs vs. Cats (kaggle 猫狗大战)
|
||||
|
||||
Create an algorithm to distinguish dogs from cats.
|
||||
|
||||
正如上面这句话所说,我们的目的就是创建一个算法,来对混合猫狗图片的数据集中,将猫和狗分别识别出来。
|
||||
|
||||
## 一、简介
|
||||
|
||||
猫狗大战这个项目其实与我们之前做的数字识别类似,只不过是图片复杂了一些。当然,我们这次使用深度学习,来完成我们想要做的事情。
|
||||
|
||||
## 二、安装包/第三方库要求
|
||||
|
||||
- Python 3.x
|
||||
- Pytorch
|
||||
|
||||
## 三、数据预处理
|
||||
|
||||
### 1、本次的数据来自 kaggle 的比赛项目 [dogs-vs-cats](https://www.kaggle.com/c/dogs-vs-cats)
|
||||
|
||||
### 2、查看数据格式
|
||||
|
||||
- 训练数据
|
||||
|
||||

|
||||
|
||||
- 训练数据集 - 说明:训练数据集中的数据,是经过人工标记的数据,类别和数字之间使用的 "." (点)做的分隔。
|
||||
|
||||
- 测试数据
|
||||
|
||||

|
||||
|
||||
- 测试数据集 - 说明:测试数据集中的数据,是没有经过人工标记的数据,没有对应的类别,只有一些相应的数字号码。
|
||||
|
||||
### 3、对数据的预处理
|
||||
|
||||
#### 3.1、提取训练 & 测试数据集的编号
|
||||
|
||||
训练数据集 & 测试数据集 给出的序号和 label 都是在文件名称中。
|
||||
|
||||
```python
|
||||
imgs = [os.path.join(root, img) for img in os.listdir(root)]
|
||||
|
||||
# test1:即测试数据集, D:/dataset/dogs-vs-cats/test1
|
||||
# train: 即训练数据集,D:/dataset/dogs-vs-cats/train
|
||||
if self.test:
|
||||
# 提取 测试数据集的序号,
|
||||
# 如 x = 'd:/path/123.jpg',
|
||||
# x.split('.') 得到 ['d:/path/123', 'jpg']
|
||||
# x.split('.')[-2] 得到 d:/path/123
|
||||
# x.split('.')[-2].split('/') 得到 ['d:', 'path', '123']
|
||||
# x.split('.')[-2].split('/')[-1] 得到 123
|
||||
imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2].split('/')[-1]))
|
||||
else:
|
||||
# 如果不是测试集的话,就是训练集,我们只切分一下,仍然得到序号,123
|
||||
imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2]))
|
||||
```
|
||||
|
||||
#### 3.2、划分训练集 & 验证集
|
||||
|
||||
首先我们知道我们手里的数据现在只有训练集和测试集,并没有验证集。那么为了我们训练得到的模型更好地拟合我们的测试数据,我们人为地将训练数据划分为 训练数据 + 验证数据(比例设置为 7:3)
|
||||
|
||||
```python
|
||||
# 获取图片的数量
|
||||
imgs_num = len(imgs)
|
||||
|
||||
# 划分训练、验证集,验证集:训练集 = 3:7
|
||||
# 判断是否为测试集
|
||||
if self.test:
|
||||
# 如果是 测试集,那么 就直接赋值
|
||||
self.imgs = imgs
|
||||
# 判断是否为 训练集
|
||||
elif train:
|
||||
# 如果是训练集,那么就把数据集的开始位置的数据 到 70% 部分的数据作为训练集
|
||||
self.imgs = imgs[:int(0.7 * imgs_num)]
|
||||
else:
|
||||
# 这种情况就是划分验证集啦,从 70% 部分的数据 到达数据的末尾,全部作为验证集
|
||||
self.imgs = imgs[int(0.7 * imgs_num):]
|
||||
```
|
||||
|
||||
#### 3.3、测试集,验证集和训练集的数据转换
|
||||
|
||||
```python
|
||||
# 数据的转换操作,测试集,验证集,和训练集的数据转换有所区别
|
||||
if transforms is None:
|
||||
# 如果转换操作没有设置,那我们设置一个转换
|
||||
normalize = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
|
||||
# 测试集 和 验证集 的转换
|
||||
# 判断如果是测试集或者不是训练集(也就是说是验证集),就应用我们下边的转换
|
||||
if self.test or not train:
|
||||
self.trainsforms = T.Compose([T.Resize(224), T.CenterCrop(224), T.ToTensor(), normalize])
|
||||
else:
|
||||
# 如果是测试集的话,使用另外的转换
|
||||
self.transforms = T.Compose([T.Resize(256), T.RandomResizedCrop(224), T.RandomHorizontalFlip(), T.ToTensor(), normalize])
|
||||
```
|
||||
|
||||
#### 3.4、重写子类 / 函数
|
||||
|
||||
这里我们使用了 torch.utils.data 中的一些函数,比如 Dataset
|
||||
|
||||
class torch.utils.data.Dataset 表示 Dataset 的抽象类,所有其他的数据集都应继承该类。所有子类都应该重写 __len__ ,提供数据集大小的方法,和 __getitem__ ,支持从 0 到 len(self) 整数索引的方法。
|
||||
|
||||
```python
|
||||
def __len__(self):
|
||||
return len(self.imgs)
|
||||
|
||||
def __getitem__(self, index):
|
||||
img_path = self.imgs[index]
|
||||
# 判断,如果是测试集的数据的话,那就返回对应的序号,比如 d:path/123.jpg 返回 123
|
||||
if self.test:
|
||||
label = int(self.imgs[index].split('.')[-2].split('/')[-1])
|
||||
else:
|
||||
# 如果不是测试集的数据,那么会有相应的类别(label),也就是对应的dog 和 cat,dog 为 1,cat 为0
|
||||
label = 1 if 'dog' in img_path.split('/')[-1] else 0
|
||||
# 这里使用 Pillow 模块,使用 Image 打开一个图片
|
||||
data = Image.open(img_path)
|
||||
# 使用我们定义的 transforms ,将图片转换,详情参考:https://pytorch.org/docs/stable/torchvision/transforms.html#transforms-on-pil-image
|
||||
# 默认的 transforms 设置的是 none
|
||||
data = self.transforms(data)
|
||||
# 将转换完成的 data 以及对应的 label(如果有的话),返回
|
||||
return data,label
|
||||
```
|
||||
|
||||
#### 3.5、数据加载
|
||||
|
||||
```python
|
||||
# 训练数据集的路径
|
||||
train_path = 'D:/dataset/dogs-vs-cats/train'
|
||||
# 从训练数据集的存储路径中提取训练数据集
|
||||
train_dataset = GetData(train_path, train=True)
|
||||
# 将训练数据转换成 mini-batch 形式
|
||||
load_train = data.DataLoader(train_dataset, batch_size=20, shuffle=True, num_workers=1)
|
||||
|
||||
# 测试数据的获取
|
||||
# 首先设置测试数据的路径
|
||||
test_path = 'D:/dataset/dogs-vs-cats/test1'
|
||||
# 从测试数据集的存储路径中提取测试数据集
|
||||
test_path = GetData(test_path, test=True)
|
||||
# 将测试数据转换成 mini-batch 形式
|
||||
loader_test = data.DataLoader(test_dataset, batch_size=3, shuffle=True, num_workers=1)
|
||||
```
|
||||
|
||||
## 四、构建 CNN 模型
|
||||
|
||||
```python
|
||||
# 调用我们现成的 AlexNet() 模型
|
||||
cnn = AlexNet()
|
||||
# 将模型打印出来观察一下
|
||||
print(cnn)
|
||||
```
|
||||
|
||||
## 五、设置相应的优化器和损失函数
|
||||
|
||||
我们已经构造完成了 CNN 模型,并将我们所需要的数据进行了相应的预处理。那我们接下来的一步就是定义相应的损失函数和优化函数。
|
||||
|
||||
torch.optim 是一个实现各种优化算法的软件包。
|
||||
|
||||
```python
|
||||
# 设置优化器和损失函数
|
||||
# 这里我们使用 Adam 优化器,使用的损失函数是 交叉熵损失
|
||||
optimizer = torch.optim.Adam(cnn.parameters(), lr=0.005, betas=(0.9, 0.99)) # 优化所有的 cnn 参数
|
||||
loss_func = nn.CrossEntropyLoss() # 目标 label 不是 one-hotted 类型的
|
||||
```
|
||||
|
||||
## 六、训练模型
|
||||
|
||||
数据以及相对应的损失函数和优化器,我们都已经设置好了,那接下来就是紧张刺激的训练模型环节了。
|
||||
|
||||
```python
|
||||
# 训练模型
|
||||
# 设置训练模型的次数,这里我们设置的是 10 次,也就是用我们的训练数据集对我们的模型训练 10 次,为了节省时间,我们可以只训练 1 次
|
||||
EPOCH = 10
|
||||
# 训练和测试
|
||||
for epoch in range(EPOCH):
|
||||
num = 0
|
||||
# 给出 batch 数据,在迭代 train_loader 的时候对 x 进行 normalize
|
||||
for step, (x, y) in enumerate(loader_train):
|
||||
b_x = Variable(x) # batch x
|
||||
b_y = Variable(y) # batch y
|
||||
|
||||
output = cnn(b_x) # cnn 的输出
|
||||
loss = loss_func(output, b_y) # 交叉熵损失
|
||||
optimizer.zero_grad() # 在这一步的训练步骤上,进行梯度清零
|
||||
loss.backward() # 反向传播,并进行计算梯度
|
||||
optimizer.step() # 应用梯度
|
||||
|
||||
# 可以打印一下
|
||||
# print('-'*30, step)
|
||||
if step % 20 == 0:
|
||||
num += 1
|
||||
for _, (x_t, y_test) in enumerate(loader_test):
|
||||
x_test = Variable(x_t) # batch x
|
||||
test_output = cnn(x_test)
|
||||
pred_y = torch.max(test_output, 1)[1].data.squeeze()
|
||||
accuracy = sum(pred_y == y_test) / float(y_test.size(0))
|
||||
print('Epoch: ', epoch, '| Num: ', num, '| Step: ', step, '| train loss: %.4f' % loss.data[0], '| test accuracy: %.4f' % accuracy)
|
||||
```
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
* git 是一个版本控制工具.
|
||||
* Github 是一个基于 git 的社会化代码分享社区, 所谓 social coding.
|
||||
* 开源项目是可以免费托管到 GitHub 上面, 在 GitHub 上你基本上可以找到任何你想要的代码.
|
||||
*开源项目是可以免费托管到GitHub上面,在GitHub上你基本上可以找到任何你想要的代码。
|
||||
|
||||
## 基本用途
|
||||
|
||||
|
@ -18,9 +18,9 @@
|
|||
|
||||
## 下载地址
|
||||
|
||||
### 1.客户端安装(三种方式都可行)
|
||||
### 1.客户端安装(例如:Mac 三种方式都可行)
|
||||
|
||||
> (一 客户端操作: https://desktop.github.com/
|
||||
> (一 客户端操作: https://desktop.github.com/ 【不推荐,程序员建议命令行】
|
||||
|
||||
> (二 通过 homebrew 安装 git
|
||||
|
||||
|
@ -109,6 +109,10 @@ jiangzl@jiangzhongliandeMacBook-Pro:~$
|
|||
<img src="../../static/images/docs/GitHub/ApacheCN-GitHub入门操作-Fork到PullRequests.png">
|
||||
</a>
|
||||
|
||||
全局概况图(看不懂就多看几遍)
|
||||
|
||||

|
||||
|
||||
> 一) fork apachecn/kaggle 项目
|
||||
|
||||

|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
# [Kaggle](https://www.kaggle.com) 入门操作指南
|
||||
|
||||
## [注册](https://www.kaggle.com/?login=true)
|
||||
|
||||
1. 首先注册账号
|
||||
2. 关联 GitHub 账号
|
||||
|
||||

|
||||
|
||||
## [竞赛 - competitions](https://www.kaggle.com/competitions)
|
||||
|
||||
* [选择 - All 和 Getting Started](https://www.kaggle.com/competitions?sortBy=deadline&group=all&page=1&pageSize=20&segment=gettingStarted)
|
||||
|
||||

|
||||
|
||||
* [选择 - Digit Recognizer(数字识别器)](https://www.kaggle.com/c/digit-recognizer)
|
||||
|
||||

|
||||
|
||||
* [阅读资料 - Digit Recognizer(数字识别器)](https://www.kaggle.com/c/digit-recognizer)
|
||||
|
||||
**选择 版本框架 和 star 最高的 Kernels 编辑就行,然后模仿 [**数字识别**](/competitions/getting-started/digit-recognizer) 案例更新**
|
||||
|
||||

|
||||
|
||||
## 项目规范(以:DigitRecognizer 为例)
|
||||
|
||||
> 文档:结尾文件名为项目名.md
|
||||
|
||||
* 案例:`competitions/getting-started/digit-recognizer.md`
|
||||
* 例如:数字识别,文档是属于 `competitions -> GettingStarted` 下面,所以创建 `competitions/getting-started` 存放文档就行
|
||||
|
||||
> 图片:结尾文件名可自由定义
|
||||
|
||||
* 案例:`static/images/comprtitions/getting-started/digit-recognizer/front_page.png`
|
||||
* 例如:数字识别,图片是属于 `competitions -> GettingStarted -> DigitRecognizer` 下面,所以创建 `competitions/getting-started/digit-recognizer` 存放文档的图片就行
|
||||
|
||||
|
||||
> 代码:结尾文件名可自由定义.py
|
||||
|
||||
* 案例:`src/python/getting-started/digit-recognizer/dr_knn_pandas.py`
|
||||
* 例如:数字识别,代码只有 `竞赛` 有,所以直接创建 `getting-started/digit-recognizer` 存放代码就行
|
||||
* 要求(方法:完全解耦)
|
||||
1. 加载数据
|
||||
2. 预处理数据(可没)
|
||||
3. 训练模型
|
||||
4. 评估模型(可没)
|
||||
5. 导出数据
|
||||
* 标注python和编码格式
|
||||
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8
|
||||
```
|
||||
|
||||
* 标注项目的描述
|
||||
|
||||
```python
|
||||
'''
|
||||
Created on 2017-10-26
|
||||
Update on 2017-10-26
|
||||
Author: 【如果是个人】片刻
|
||||
Team: 【如果是团队】装逼从不退缩(张三、李四 等等)
|
||||
Github: https://github.com/apachecn/kaggle
|
||||
'''
|
||||
```
|
||||
|
||||
> 数据:结尾文件名可自由定义
|
||||
|
||||
* 输入:`datasets/getting-started/digit-recognizer/input/train.csv`
|
||||
* 输出:`datasets/getting-started/digit-recognizer/ouput/Result_sklearn_knn.csv`
|
||||
* 例如:数字识别,数据只有 `竞赛` 有,所以直接创建 `getting-started/digit-recognizer` 存放数据就行
|
||||
|
||||
> 结果提交
|
||||
|
||||
将数据的输出结果提交到项目的页面中
|
||||
|
||||
<a href="https://www.kaggle.com/c/digit-recognizer/submit" target="_blank">
|
||||
<img src="../static/images/docs/kaggle-submit.jpg">
|
||||
</a>
|
||||
|
||||
## docs目录(可忽略)
|
||||
|
||||
`docs 目录存放的是 ApacheCN 整理的操作or说明文档,和 kaggle 网站内容没有关系`
|
||||
|
||||
**后面会持续更新**
|
|
@ -14,15 +14,15 @@ import numpy as np
|
|||
import pandas as pd
|
||||
from sklearn.decomposition import PCA
|
||||
from sklearn.neighbors import KNeighborsClassifier
|
||||
import sys
|
||||
|
||||
data_dir = '/opt/data/kaggle/getting-started/digit-recognizer/'
|
||||
|
||||
data_dir = '/Users/wuyanxue/Documents/GitHub/datasets/getting-started/digit-recognizer/'
|
||||
|
||||
# 加载数据
|
||||
def opencsv():
|
||||
# 使用 pandas 打开
|
||||
data = pd.read_csv(os.path.join(data_dir, 'train.csv'))
|
||||
data1 = pd.read_csv(os.path.join(data_dir, 'test.csv'))
|
||||
data = pd.read_csv(os.path.join(data_dir, 'input/train.csv'))
|
||||
data1 = pd.read_csv(os.path.join(data_dir, 'input/test.csv'))
|
||||
|
||||
train_data = data.values[0:, 1:] # 读入全部训练数据, [行,列]
|
||||
train_label = data.values[0:, 0] # 读取列表的第一列
|
||||
|
@ -95,9 +95,9 @@ def dRecognition_knn():
|
|||
|
||||
# 结果预测
|
||||
testLabel = knnClf.predict(testData)
|
||||
|
||||
|
||||
# 结果的输出
|
||||
saveResult(testLabel, os.path.join(data_dir, 'Result_sklearn_knn.csv'))
|
||||
saveResult(testLabel, os.path.join(data_dir, 'output/Result_sklearn_knn.csv'))
|
||||
print("finish!")
|
||||
stop_time_r = time.time()
|
||||
print('classify time used:%f' % (stop_time_r - start_time))
|
||||
|
|
|
@ -9,22 +9,26 @@ Github: https://github.com/apachecn/kaggle
|
|||
PCA主成成分分析
|
||||
'''
|
||||
|
||||
import os.path
|
||||
import csv
|
||||
import time
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
from sklearn.decomposition import PCA
|
||||
from sklearn.svm import SVC
|
||||
from sklearn.metrics import classification_report
|
||||
from sklearn.model_selection import train_test_split
|
||||
|
||||
# 数据路径
|
||||
data_dir = '/Users/wuyanxue/Documents/GitHub/datasets/getting-started/digit-recognizer/'
|
||||
|
||||
# 加载数据
|
||||
def opencsv():
|
||||
print('Load Data...')
|
||||
# 使用 pandas 打开
|
||||
dataTrain = pd.read_csv('datasets/getting-started/digit-recognizer/input/train.csv')
|
||||
dataPre = pd.read_csv('datasets/getting-started/digit-recognizer/input/test.csv')
|
||||
dataTrain = pd.read_csv(os.path.join(data_dir, 'input/train.csv'))
|
||||
dataPre = pd.read_csv(os.path.join(data_dir, 'input/test.csv'))
|
||||
trainData = dataTrain.values[:, 1:] # 读入全部训练数据
|
||||
trainLabel = dataTrain.values[:, 0]
|
||||
preData = dataPre.values[:, :] # 测试全部测试个数据
|
||||
|
@ -57,6 +61,7 @@ def dRCsv(x_train, x_test, preData, COMPONENT_NUM):
|
|||
return pcaTrainData, pcaTestData, pcaPreData
|
||||
|
||||
|
||||
|
||||
# 训练模型
|
||||
def trainModel(trainData, trainLabel):
|
||||
print('Train SVM...')
|
||||
|
@ -179,7 +184,6 @@ def getModel(filename):
|
|||
fr = open(filename, 'rb')
|
||||
return pickle.load(fr)
|
||||
|
||||
|
||||
def trainDRSVM():
|
||||
startTime = time.time()
|
||||
|
||||
|
@ -188,8 +192,8 @@ def trainDRSVM():
|
|||
# 模型训练 (数据预处理-降维)
|
||||
optimalSVMClf, pcaPreData = getOptimalAccuracy(trainData, trainLabel, preData)
|
||||
|
||||
storeModel(optimalSVMClf, 'datasets/getting-started/digit-recognizer/ouput/Result_sklearn_SVM.model')
|
||||
storeModel(pcaPreData, 'datasets/getting-started/digit-recognizer/ouput/Result_sklearn_SVM.pcaPreData')
|
||||
storeModel(optimalSVMClf, os.path.join(data_dir, 'output/Result_sklearn_SVM.model'))
|
||||
storeModel(pcaPreData, os.path.join(data_dir, 'output/Result_sklearn_SVM.pcaPreData'))
|
||||
|
||||
print("finish!")
|
||||
stopTime = time.time()
|
||||
|
@ -199,25 +203,42 @@ def trainDRSVM():
|
|||
def preDRSVM():
|
||||
startTime = time.time()
|
||||
# 加载模型和数据
|
||||
optimalSVMClf = getModel('datasets/getting-started/digit-recognizer/ouput/Result_sklearn_SVM.model')
|
||||
pcaPreData = getModel('datasets/getting-started/digit-recognizer/ouput/Result_sklearn_SVM.pcaPreData')
|
||||
optimalSVMClf = getModel(os.path.join(data_dir, 'output/Result_sklearn_SVM.model'))
|
||||
pcaPreData = getModel(os.path.join(data_dir, 'output/Result_sklearn_SVM.pcaPreData'))
|
||||
|
||||
# 结果预测
|
||||
testLabel = optimalSVMClf.predict(pcaPreData)
|
||||
# print("testLabel = %f" % testscore)
|
||||
# 结果的输出
|
||||
saveResult(testLabel, 'datasets/getting-started/digit-recognizer/ouput/Result_sklearn_SVM.csv')
|
||||
saveResult(testLabel, os.path.join(data_dir, 'output/Result_sklearn_SVM.csv'))
|
||||
print("finish!")
|
||||
stopTime = time.time()
|
||||
print('PreModel load time used:%f s' % (stopTime - startTime))
|
||||
|
||||
# 数据可视化
|
||||
def dataVisulization(data, labels):
|
||||
pca = PCA(n_components=2, whiten=True) # 使用PCA方法降到2维
|
||||
pca.fit(data)
|
||||
pcaData = pca.transform(data)
|
||||
uniqueClasses = set(labels)
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(1, 1, 1)
|
||||
for cClass in uniqueClasses:
|
||||
plt.scatter(pcaData[labels==cClass, 0], pcaData[labels==cClass, 1])
|
||||
plt.xlabel('$x_1$')
|
||||
plt.ylabel('$x_2$')
|
||||
plt.title('MNIST visualization')
|
||||
plt.show()
|
||||
|
||||
if __name__ == '__main__':
|
||||
trainData, trainLabel, preData = opencsv()
|
||||
dataVisulization(trainData, trainLabel)
|
||||
|
||||
|
||||
# 训练并保存模型
|
||||
trainDRSVM()
|
||||
#trainDRSVM()
|
||||
|
||||
# 分析数据
|
||||
analyse_data(trainData)
|
||||
#analyse_data(trainData)
|
||||
# 加载预测数据集
|
||||
# preDRSVM()
|
||||
#preDRSVM()
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Loading…
Reference in New Issue