TF 学习之数据预处理坑---【如何选取训练集和测试集】

鸢尾花(iris)数据集,一个很经典的公开数据集。想用其学习分类学习,还是在数据预处理部分遇到了问题:

第一,该数据集中的数据包括 4 个 features 和 3 个 lables。其中 lables 是字符串,并非我熟知的 0,1,2。那么在分类问题最后的分类输出阶段作比较时,能用非数值型 lables 直接比较么?

第二,该数据集中的三类花,每种我都想各抽取一部分作为训练集,剩余没有选中的作为测试集。代码实现要怎样做?

再次感谢这一周中为我不厌其烦解答问题的各位大神!:grimacing:

第二个问题自己解决了,代码在一楼,但是没有用 TF 解决,借鉴了 sklearn,我希望有人能给我给出 TF 的解决方案! :stuck_out_tongue_winking_eye:

from sklearn.model_selection import train_test_split
data, lables = load_data ('csv_test.csv')
train_data, train_lables, test_data, test_lables = train_test_split (data, lables, test_size=0.3, random_state=33)
random_state 如果不设置一个数值,那么每次生成的训练集和测试集不一样

下面附上数据集。(数据集有个坑…坑了我一下午,最后有一条空数据,记得手动删除)

五楼,自己做的,数据预处理完整版有比我好的思想方法的,大家共同探讨。

iris.rar (852 字节)


M 丶 Sulayman,发表于 2018-4-29 10:29:17

不容易啊,第二个问题我竟然自己解决了

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import numpy as np
from sklearn.model_selection import train_test_split


def load_data (file):
    features = []
    lables = []
    file = open (file, 'r')
    lines = file.readlines ()
    for line in lines:
        items = line.strip ().split (',')
        lables.append (int (float (items [-1])))
        feature = []
        for i in range (len (items) - 1):
            feature.append (int (float (items [i])))
        features.append (feature)
    return np.array (features), np.array (lables)

if __name__ == '__main__':
    data, lables = load_data ('csv_test.csv')
    train_data, train_lables, test_data, test_lables = train_test_split (data,
                                                                        lables,
                                                                        test_size=0.3,
                                                                        random_state=33)
    print (train_data)
    print (train_lables)
    print (test_data)
    print (test_lables)

M 丶 Sulayman(提问者),发表于 2018-4-29 11:05:29

第一个问题,我感觉我问的有点傻吧…一般情况下,都想到的是先转换标签量吧


M 丶 Sulayman(提问者),发表于 2018-4-29 11:18:47

新问题:如何从数据中选取出的各类别标签的训练集和测试集分别占总训练集和总测试集的比例相同?


M 丶 Sulayman(提问者),发表于 2018-4-29 11:25:09

数据预处理完整版

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import numpy as np


def load_data (file):
    train_features = []
    train_lables = []
    file = open (file, 'r')
    lines = file.readlines ()
    for line in lines:
        items = line.strip ().split (',')

        list_to_string = ','.join (items)
        for ch in ['Iris-setosa']:
            if ch in list_to_string:
                list_to_string = list_to_string.replace (ch, '0')
        for ch in ['Iris-versicolor']:
            if ch in list_to_string:
                list_to_string = list_to_string.replace (ch, '1')
        for ch in ['Iris-virginica']:
            if ch in list_to_string:
                list_to_string = list_to_string.replace (ch, '2')

        items = list_to_string.strip ().split (',')

        train_features.append ([float (items [i]) for i in range (len (items) - 1)])
        train_lables.append (float (items [-1]))

    return np.array (train_features), np.array (train_lables)

if __name__ == '__main__':
    data, lables = load_data ('iris.csv')

    print (data)
    print (lables)

M 丶 Sulayman(提问者),发表于 2018-4-29 18:11:23

把三个 lables 转换为 0,1,2


M 丶 Sulayman(提问者),发表于 2018-4-29 18:13:35

借鉴的该方法


M 丶 Sulayman(提问者),发表于 2018-4-29 18:14:21

问题一

既然你已经安装了 sklearn 库,那么有一种更便捷的加载鸢尾花数据集的方式:

# python 3.x
from sklearn.datasets import load_iris

# 以字典形式加载鸢尾花数据集
iris = load_iris ()
# 使用 X 表示数据集中的属性数据
X = iris.data 
# 使用 y 表示数据集中的标签
y = iris.target 
# X 是一个 150x4 的 numpy 数组,表示有 150 条数据,每条数据有四个特征值
print (X.shape) # (150, 4)
# y 是一个 150x1 的 numpy 数组,表示 150 条数据的标签值
print (y.shape) # (150, )

问题二

sklearn 库中的 train_test_split 函数 似乎并不能保证 划分的训练集和测试集中各类花的比例相同, 它只是根据所给的比例随机划分。

可以参看 该函数的文档 以及 该函数的实现源代码

此外,TF 中似乎并没有类似划分数据集的函数可以调用。


Zerone01,发表于 2018-4-29 21:39:52

额,加载的这种,没法学习到用自己的数据集做模型,不过我今天自己解决了 5 楼的代码你看看,我自己在你昨天给我的代码的基础上增加了转换。

嗯,你说的这个问题是对的,它确实没法做到相同比例划分。我还在看一些代码,希望自己能跑出来~


M 丶 Sulayman (提问者),发表于 2018-4-29 21:42:29

五楼的写法没有错,但是我觉得还可以更简洁一些

# 存储三种花的种类名称
categories = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']

def load_data (file):
    train_features = []
    train_lables = []
    file = open (file, 'r')
    lines = file.readlines ()
    for line in lines:
        items = line.strip ().split (',')  # items 形如:['5.1','3.5','1.4','0.2','Iris-setosa']
        train_features.append ([float (items) for i in range (len (items) - 1)])
        train_lables.append (categories.index (items [-1]))
    return np.array (train_features), np.array (train_lables)

这里用到了 listindex 方法,直接将花的种类名传入到 categories.index () 中,可以得到该种类名在列表中的索引值,即:
传入 'Iris-setosa' 得到 0
传入 'Iris-versicolor' 得到 1
传入 'Iris-virginica' 得到 2


Zerone01,发表于 2018-4-29 21:58:37

等你一天了,我就觉得我自己的有点啰嗦,666666,这代码风格很赞,继续学习,再次感谢!~


M 丶 Sulayman(提问者),发表于 2018-4-29 22:04:11

我也是刚刚想出来的.
话说你好勤奋啊, 放假仍然坚持学习,佩服佩服


Zerone01,发表于 2018-4-29 22:13

你能再帮我看看这个么…代码太薄弱,上面感觉写的也有点啰嗦。我感觉可以解决我说的那个按相同比例划分数据集。
https://blog.csdn.net/duxu24/article/details/74012232
谢谢~


M 丶 Sulayman (提问者),发表于 2018-4-29 22:38:15

确实可以解决,你用的时候可以把它那些输出信息的代码删除,核心代码在于调用的 sklearn 库的 StratifiedShuffleSplit 方法.
但是我看官方文档上的用法和那个人的写的不太一样:
http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedShuffleSplit.html
你可以自己尝试一下


Zerone01,发表于 2018-4-30 09:11

用 tf.data.Dataset 的方法:

import tensorflow as tf

dataset = tf.data.TextLineDataset ('iris.csv')
table = tf.contrib.lookup.index_table_from_tensor (
    ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
)

def _parse_function (line):
    default_val = [[0.], [0.], [0.], [0.], ['']]
    data = tf.decode_csv (line, default_val)
    features = tf.stack (data [:-1])
    targets = table.lookup (data [-1])
    return features, targets

batched_dataset = dataset.apply (tf.contrib.data.map_and_batch (
    map_func=_parse_function, batch_size=2))
iterator = batched_dataset.make_initializable_iterator ()

next_element = iterator.get_next ()
with tf.Session () as sess:
    sess.run ((tf.tables_initializer (), iterator.initializer))
    print (sess.run (next_element))
    print (sess.run (next_element))


yunhai_luo,发表于 2018-4-30 02:33:22

先感谢!~我慢慢学习一下,还没接触过这些函数,不懂我再问~


M 丶 Sulayman(提问者),发表于 2018-4-30 09:05:41

我在做 cnn 图像复原的工作,这要求以清晰图像作为标签,请教一下您知道该怎么做么?


bitxrj,发表于 2018-5-2 09:59:33

这个确实没做过。不过以我的认知,图像标注都是手动的吧。你首先要定义什么样的图像被称为清晰图像,然后给它一个 lable 就好了,不清晰的也给它一个相应的 lable。扔到 CNN 中去训练。举个例子手写数字识别 2828 维图像,扔进模型就是 7841 的数据外加一个标签(0~9)。所以关键在于你如何定义清晰图像,而标签很简单啊。这是我的理解,错了请指正。


M 丶 Sulayman(提问者),发表于 2018-5-2 10:08:07

bitxrj:

清晰和模糊图像是分好的,分别在两个文件夹里的。您说的我再想想看可不可以做。做毕设做的满头包,很久没进度了,再弄不好老师怕是要动刀子了 22333
2018-5-2 10:41

M 丶 Sulayman:

回复 bitxrj :分好了,手动加标签,然后想想,扔进网络里面的特征出了图像还应该有一些对清晰度判别的特征属性,关键在这里。
2018-5-2 16:06

M 丶 Sulayman:

回复 bitxrj :emmmmm…我刚看了你在另一篇帖子的回复,我还是不要班门弄斧了我上面说的都是自己的想法…没搞过图像,最多理解 MNIST 识别,抱歉抱歉,我就不胡诌了
2018-5-2 16:28 回复

bitxrj:

回复 M 丶 Sulayman :不会,我就是小白,还在学习中。。


M 丶 Sulayman(提问者) & bitxrj,发表于 2018-5-2 16:31

求数据集专题教程啊


jka,发表于 2018-7-4 10:45:48