使用飞桨框架搭建多层感知器

这里有个bug的点,paddle框架自带的波士顿房价dataset和我自己的dataset, __item__方法返回的都是一个元组,用 a,b = train_dataset=[0]的话那就是两个np数组


(array([-1.0423225 , -0.24851945, -1.0652921 , -1.0532238 , -0.43834025,
        -0.19826205, -0.58423096, -0.24698801, -0.09784286, -0.04000573,
        -1.188272  , -0.7809258 , -0.6200115 , -0.28191438, -0.5774179 ,
...

        -1.2297674 , -0.8086368 , -0.564268  , -0.61155623, -0.82438904,
        -0.10260557, -0.7286519 ,  0.        , -1.2983824 , -1.155188  ,
        -1.1353154 , -0.51228553, -0.9952254 , -0.35158026, -0.33337447],
       dtype=float32),
 array(0, dtype=int64))

(array([-0.0405441 ,  0.06636364, -0.32356227, -0.06916996, -0.03435197,
        0.05563625, -0.03475696,  0.02682186, -0.37171335, -0.21419304,
       -0.33569506,  0.10143217, -0.21172912]),
array([24.]))

我寻思他们也没差别,但问题很明显是锁定在dataset上面,下面表格应该很好地反应出来,相关度拉满好吧。

自建dataset飞桨dataset

自己的dataset扔进去就愣报错好吧

ValueError: (InvalidArgument) The type of data we are trying to retrieve does not match the type of data currently contained in the container.

[Hint: Expected y_dims[y_ndim - 2] == K, but received y_dims[y_ndim - 2]:30 != K:13.] (at C:\home\workspace\Paddle_release\paddle/phi/kernels/impl/matmul_kernel_impl.h:315)
[operator < matmul_v2 > error]

不过我又发现,如果n_input的值没有和输入特征对应的话也会出现error,于是我锁定了以下这段代码

n_input = len(x[0])

from paddle import nn
lenet_Sequential = nn.Sequential(
    nn.Linear(n_input, 1,)
)

我以为是 len(x[0])的问题,于是直接让 n_input=30但还是报错,重新看发现两次报的其实错误不同,指并不是n_input不匹配的问题
他说我传入的数据类型不匹配,但自建的dataset和飞桨的dataset读出来的数据类型其实也没那么多不同,这让我非常困惑。于是我去看了UCIHousing的源代码

def __getitem__(self, idx):
    data = self.data[idx]
    return np.array(data[:-1]).astype(self.dtype), \
            np.array(data[-1:]).astype(self.dtype)

而设置 self.data部分的代码在 _load_data方法中

def _load_data(self, feature_num=14, ratio=0.8):
    data = np.fromfile(self.data_file, sep=' ')
    data = data.reshape(data.shape[0] // feature_num, feature_num)
    maximums, minimums, avgs = data.max(axis=0), data.min(axis=0), data.sum(
        axis=0) / data.shape[0]
    for i in six.moves.range(feature_num - 1):
        data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])
    offset = int(data.shape[0] * ratio)
    if self.mode == 'train':
        self.data = data[:offset]
    elif self.mode == 'test':
        self.data = data[offset:]

前两步的话知识把data从保存的文件中读出然后变形,在UCIHousing中data应该是一个一维张量,第二行应该是在做切分(13个特征+1个标签),接下来的两行是通过一个二元函数对特征值进行放缩,然后offset开始切分数据集为训练集和测试集
那我明白了, __getitem__这里其实也就是读取每一行,然后拆分出feature和label,但无论怎么样我的dataset和飞桨的dataset在 type()下的输出结果还是相同的,一个是 tuple numpy.ndarray,另一个是 <class 'tuple'></class> <class 'numpy.ndarray'></class>
我就不明白了,这两个dataset已经像的不能再像了,怎么还是不行,盖亚啊啊啊!!!!!!!!!!!!!!!!!!!!!!
你说咋的,当我把上面这段代码改为下面这段之后,模型训练那步能跑了,当我开心的呀看着他转了好久还不出来,心想大事不妙


def __getitem__(self, index):
    feature = np.array(self.data_list[index][:-1]).astype('float32')
    label = np.array(self.data_list[index][-1:]).astype('int64')

    return feature, label

def __getitem__(self, index):
    data = self.data_list[index]
    feature = np.array(data[:-1]).astype('float32')
    label = np.array(data[index][-1:]).astype('int64')

    return feature, label

果然报错了 IndexError: list index out of range
那我又去看了 model.fit的源代码,想看一下他到底是怎么样访问的
我用这段代码对HCIHousing的dataset进行访问是没有问题的,非常OK

for i in range(len(train_dataset)):
    print(train_dataset.__getitem__(i)[1])

但对于自个的dataset而言果不其然地报错

{
    "name": "IndexError",
    "message": "invalid index to scalar variable.",
    "stack": "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mIndexError\u001b[0m                                Traceback (most recent call last)\n\u001b[1;32md:\\&#x9879;&#x76EE;\\&#x8BA9;&#x6211;&#x4EEC;&#x8361;&#x8D77;&#x98DE;&#x6868;\\&#x98DE;&#x6868;_&#x82F1;&#x96C4;&#x8054;&#x76DF;\\main.ipynb Cell 5\u001b[0m in \u001b[0;36m<cell 1 line:>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      <a href="vscode-notebook-cell:/d%3A/%E9%A1%B9%E7%9B%AE/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%8D%A1%E8%B5%B7%E9%A3%9E%E6%A1%A8/%E9%A3%9E%E6%A1%A8_%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F/main.ipynb#X11sZmlsZQ%3D%3D?line=0">1</a>\u001b[0m \u001b[39mfor\u001b[39;00m i \u001b[39min\u001b[39;00m \u001b[39mrange\u001b[39m(\u001b[39mlen\u001b[39m(train_dataset)):\n\u001b[1;32m----> <a href="vscode-notebook-cell:/d%3A/%E9%A1%B9%E7%9B%AE/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%8D%A1%E8%B5%B7%E9%A3%9E%E6%A1%A8/%E9%A3%9E%E6%A1%A8_%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F/main.ipynb#X11sZmlsZQ%3D%3D?line=1">2</a>\u001b[0m     \u001b[39mprint\u001b[39m(train_dataset\u001b[39m.\u001b[39;49m\u001b[39m__getitem__\u001b[39;49m(i)[\u001b[39m1\u001b[39m])\n\n\u001b[1;32md:\\&#x9879;&#x76EE;\\&#x8BA9;&#x6211;&#x4EEC;&#x8361;&#x8D77;&#x98DE;&#x6868;\\&#x98DE;&#x6868;_&#x82F1;&#x96C4;&#x8054;&#x76DF;\\main.ipynb Cell 5\u001b[0m in \u001b[0;36mMyDataset.__getitem__\u001b[1;34m(self, index)\u001b[0m\n\u001b[0;32m     <a href="vscode-notebook-cell:/d%3A/%E9%A1%B9%E7%9B%AE/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%8D%A1%E8%B5%B7%E9%A3%9E%E6%A1%A8/%E9%A3%9E%E6%A1%A8_%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F/main.ipynb#X11sZmlsZQ%3D%3D?line=21">22</a>\u001b[0m data \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mdata_list[index]\n\u001b[0;32m     <a href="vscode-notebook-cell:/d%3A/%E9%A1%B9%E7%9B%AE/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%8D%A1%E8%B5%B7%E9%A3%9E%E6%A1%A8/%E9%A3%9E%E6%A1%A8_%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F/main.ipynb#X11sZmlsZQ%3D%3D?line=22">23</a>\u001b[0m feature \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39marray(data[:\u001b[39m-\u001b[39m\u001b[39m1\u001b[39m])\u001b[39m.\u001b[39mastype(\u001b[39m'\u001b[39m\u001b[39mfloat32\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[1;32m---> <a href="vscode-notebook-cell:/d%3A/%E9%A1%B9%E7%9B%AE/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%8D%A1%E8%B5%B7%E9%A3%9E%E6%A1%A8/%E9%A3%9E%E6%A1%A8_%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F/main.ipynb#X11sZmlsZQ%3D%3D?line=23">24</a>\u001b[0m label \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39marray(data[index][\u001b[39m-\u001b[39;49m\u001b[39m1\u001b[39;49m:])\u001b[39m.\u001b[39mastype(\u001b[39m'\u001b[39m\u001b[39mint64\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[0;32m     <a href="vscode-notebook-cell:/d%3A/%E9%A1%B9%E7%9B%AE/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%8D%A1%E8%B5%B7%E9%A3%9E%E6%A1%A8/%E9%A3%9E%E6%A1%A8_%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F/main.ipynb#X11sZmlsZQ%3D%3D?line=24">25</a>\u001b[0m \u001b[39m# &#x8FD4;&#x56DE;&#x7279;&#x5F81;&#x548C;&#x5BF9;&#x5E94;&#x6807;&#x7B7E;\u001b[39;00m\n\u001b[0;32m     <a href="vscode-notebook-cell:/d%3A/%E9%A1%B9%E7%9B%AE/%E8%AE%A9%E6%88%91%E4%BB%AC%E8%8D%A1%E8%B5%B7%E9%A3%9E%E6%A1%A8/%E9%A3%9E%E6%A1%A8_%E8%8B%B1%E9%9B%84%E8%81%94%E7%9B%9F/main.ipynb#X11sZmlsZQ%3D%3D?line=25">26</a>\u001b[0m \u001b[39mreturn\u001b[39;00m feature, label\n\n\u001b[1;31mIndexError\u001b[0m: invalid index to scalar variable."
}
</cell>

还有逗的啊,我的dataset跑上面的代码能行,跑下面的不行

for i in range(len(train_dataset)):
    print(train_dataset.data_list[i][1])

但是飞桨自带的dataset就可以

for i in range(len(train_dataset)):
    print(train_dataset.__getitem__(i)[1])

我自己那个dataset只打印第一行的时候又可以 print(train_dataset.__getitem__(0))我真的不理解呀,第二行又不行了
我理解了,我代码扣错了,给label赋值那行多打了个index索引进去

def __getitem__(self, index):
    data = self.data_list[index]
    feature = np.array(data[:-1]).astype('float32')
    label = np.array(data[index][-1:]).astype('int64')

    return feature, label

我不理解哈哈哈咋还有问题,还是之前那个Invalid Value问题
又发现了一个小问题,下面这段代码打印出来的是label

for i in range(len(train_dataset)):
    print(train_dataset.__getitem__(i)[0])

这样子就能正确打印出feature和label

for i in range(len(train_dataset)):
    a,b = train_dataset.__getitem__(i)
    print(a,b)

我擦擦擦VSC崩了,我的.ipynb代码块全部空了出来,好在恢复过来了,还有一个问题是他丫的.ipynb中一调试就退出,真不好玩,我又不想用pycharm这么重量的
后来在VSC里建了一个.py文件来debug,或者叫他比较有意思的事情吧,就是我的debug第一次通过 model.fit的时候是没问题的,第二次通过的时候就抛出异常了
只是有时候气呀,明明能用高层API解决的问题,为啥要去手写底层代码
稍微看了下model.py里好像也要先把dataset转为dataloader,说实话感觉sklearn和keras做这种任务的时候让人更加轻松,直接扔numpy张量就行,或者paddle好像也没有能够直接把数据转为paddle格式的tensor,需要自己来自定义,也不是不可以吧其实说,但是的话先预处理完feature再转换tensor也不是不可以,现在主要的问题是我没有头绪
emm好像有个to_tensor方法,但是如果想要直接调用高层API model.fit的话还是不行呀
奈斯奈斯我爽了,解决了归一化的问题,利用了 np.c_[]方法,终于正常地开始训练了哈哈哈哈哈哈,不多说了直接看代码吧


df_train = pd.read_csv("train.csv")
df_train = df_train.drop(['id'],axis=1)

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(df_train.iloc[:,0:])
scaler_data = scaler.transform(df_train.iloc[:,0:])

ratio = 0.8
offset = int(df_train.shape[0] * ratio)
train_data = np.c_[scaler_data,df_train.iloc[:,0]][:offset].copy()
test_data = np.c_[scaler_data,df_train.iloc[:,0]][offset:].copy()

n_input = 30
from paddle import nn
class Classifier(paddle.nn.Layer):
    def __init__(self):
        super(Classifier, self).__init__()
        self.l1 = paddle.nn.Linear(n_input, 1,)

    def forward(self, inputs):
        pred = self.l1(inputs)
        return pred

import paddle.nn.functional as F
y_preds = []
train_nums = []
train_costs = []
labels_list = []
BATCH_SIZE = 20

def train(model):
    print('start training ... ')

    model.train()
    EPOCH_NUM = 5
    train_num = 0
    optimizer = paddle.optimizer.SGD(learning_rate=0.001, parameters=model.parameters())
    for epoch_id in range(EPOCH_NUM):

        np.random.shuffle(train_data)

        mini_batches = [train_data[k: k+BATCH_SIZE] for k in range(0, len(train_data), BATCH_SIZE)]
        for batch_id, data in enumerate(mini_batches):
            features_np = np.array(data[:, :n_input], np.float32)
            labels_np = np.array(data[:, -1:], np.float32)
            features = paddle.to_tensor(features_np)
            labels = paddle.to_tensor(labels_np)

            y_pred = model(features)
            cost = F.mse_loss(y_pred, label=labels)
            train_cost = cost.numpy()[0]

            cost.backward()

            optimizer.step()

            optimizer.clear_grad()

            if batch_id%30 == 0 and epoch_id%50 == 0:
                print("Pass:%d,Cost:%0.5f"%(epoch_id, train_cost))

            train_num = train_num + BATCH_SIZE
            train_nums.append(train_num)
            train_costs.append(train_cost)

model = Classifier()
train(model)

def draw_train_process(iters, train_costs):
    plt.title("training cost", fontsize=24)
    plt.xlabel("iter", fontsize=14)
    plt.ylabel("cost", fontsize=14)
    plt.plot(iters, train_costs, color='red', label='training cost')
    plt.show()

import matplotlib
matplotlib.use('TkAgg')
%matplotlib inline
draw_train_process(train_nums, train_costs)

当然还有一些细节没有细扣,先睡觉了,明天继续

Original: https://blog.csdn.net/frc8011_zzr/article/details/126314176
Author: frc8011_zzr
Title: 使用飞桨框架搭建多层感知器

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/663313/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球