转换为tobytes()时,它会更改numpy数组。ValueError:应为2D数组,而应为1D数组:

2024-03-28 16:35:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我在做这个套接字通信代码,将输入从server.py(笔记本电脑上)发送到client.py(raspberry pi),在这个通信中,我从2d Numpy数组一次发送一行到客户端,然后客户端使用Keras模型预测输出。通信不是问题,但问题是在套接字通信中发送数据必须以字节为单位,因此每次发送数据时,我都会将数组更改为字节,当接收到数据时,我会再次将字节返回NumPy数组。问题是,当我尝试更改模型的预测值时,它会更改该值

Server.py

import socket
import numpy as np
import pandas as pd
import sklearn
from sklearn.preprocessing import MinMaxScaler
import struct


def send_data(connection, data):
    data_size = len(data)
    data_size_as_4_bytes = struct.pack('>I', data_size)

    connection.send(data_size_as_4_bytes)    
    connection.send(data)

def recv_data(connection, chunk_size=64):
    data_size_as_4_bytes = connection.recv(4)
    data_size = struct.unpack('>I', data_size_as_4_bytes)[0]

    data = b""
    size = 0

    while size < data_size:
        chunk = connection.recv(chunk_size)
        print(chunk)
        size += len(chunk)
        data += chunk

    return data



scaler_ti = MinMaxScaler()
test_inputs = []
test_inputs = np.array(test_inputs)
temp_in = pd.read_excel(r'K:\BachelorThesis\Data\TestingData\Mix_Data_inputs.xlsx')
test_inputs = temp_in.to_numpy()
scaler_ti.fit(test_inputs)
normalized_test_inputs = scaler_ti.transform(test_inputs)




HOST = ''  
PORT = 62402

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  
s.bind((HOST, PORT))
s.listen(5)

try:
    while True:
    

        print('Waiting for client')
    
        connection, address = s.accept()
        print(f"Connection from {address} has been established!")

    
        for row in normalized_test_inputs:
    
        
            print('send:', row)
        
            data = row.tobytes()
            send_data(connection, data)


            data = recv_data(connection)
            row = np.frombuffer(data)
            print(row)
            inverse = scaler_ti.inverse_transform(row.reshape(1,8))
        
            print('recv:', inverse)


        send_data(connection, 'end'.encode())


    
        connection.close()
    
except KeyboardInterrupt:
    print("Stopped by Ctrl+C")
finally:
    s.close()

client.py

# author: Bartlomiej "furas" Burek (https://blog.furas.pl)
# date: 2021.07.23
#
# title: receiving back data from the client
# url: https://stackoverflow.com/questions/68499599/receiving-back-data- 
from-the-client/68502806#68502806
import socket
import numpy as np
from random import randint
import os
import tensorflow as tf
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.models import load_model
import struct


def send_data(connection, data):
    data_size = len(data)
    data_size_as_4_bytes = struct.pack('>I', data_size)

    connection.send(data_size_as_4_bytes)    
    connection.send(data)

def recv_data(connection, chunk_size=64):
    data_size_as_4_bytes = connection.recv(4)
    data_size = struct.unpack('>I', data_size_as_4_bytes)[0]

    data = b""
    size = 0

    while size < data_size:
        chunk = connection.recv(chunk_size)
        size += len(chunk)
        data += chunk

    return data

def Predicting(input_data):

    input_data = input_data.reshape(1,8)
    output_data = modelANN.predict(input_data)

    return output_data


modelANN = load_model(os.path.join("K:\BachelorThesis\code 
testing\TireForces.LSTM","ANN_model.h5"))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 62402
s.connect((host, port))

while True:


    data = recv_data(s)

    if data == b'end':
        break

    input_data = np.frombuffer(data)

    print('recv:', input_data)


    output_data = Predicting(input_data)


    print('send:', output_data)

    data = output_data.tobytes()
    print(data)
    send_data(s, data)



s.close()

server.py的输出

    Waiting for client
Connection from ('192.168.137.1', 52967) has been established!
send: [3.24085967e-04 3.20361343e-04 3.52129031e-04 3.77033700e-04
 6.79706856e-01 4.95983138e-01 4.52484158e-04 4.92325891e-01]
b"\x0e\x97/?\xf4\xe68?|\x18)?B\x1c}>\xc5\xd7'?\xf2\xd7\n?=\xe5\x1b?)\x1f\xcb>"
[3.79976874e-04 1.08444638e-07 5.11999896e-05 3.23316134e-06]
Traceback (most recent call last):
  File "K:\BachelorThesis\code testing\server.py", line 74, in <module>
     inverse = scaler_ti.inverse_transform(row.reshape(1,8))
ValueError: cannot reshape array of size 4 into shape (1,8)

client.py的输出

recv: [3.24085967e-04 3.20361343e-04 3.52129031e-04 3.77033700e-04
  6.79706856e-01 4.95983138e-01 4.52484158e-04 4.92325891e-01]
send: [[0.68589866 0.72227407 0.66052985 0.24717811 0.65563613 0.54235756
  0.60896665 0.3967221 ]]
b"\x0e\x97/?\xf4\xe68?|\x18)?B\x1c}>\xc5\xd7'?\xf2\xd7\n?=\xe5\x1b?)\x1f\xcb>"
Traceback (most recent call last):
  File "K:\BachelorThesis\code testing\client.py", line 50, in <module>
    data = recv_data(s)
  File "K:\BachelorThesis\code testing\client.py", line 20, in recv_data
    data_size = struct.unpack('>I', data_size_as_4_bytes)[0]
struct.error: unpack requires a buffer of 4 bytes

Tags: frompyimportclientsenddatasizebytes
1条回答
网友
1楼 · 发布于 2024-03-28 16:35:38

tobytes只是数组数据缓冲区的字节副本。它不传递任何数据类型或形状信息:

In [31]: x = np.arange(12).reshape((3,4))
In [32]: astr = x.tobytes()
In [33]: astr
Out[33]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0...\x00\x00\x00'

根据文档,默认加载为float64:

In [34]: y = np.frombuffer(astr)
In [35]: y
Out[35]: 
array([0.0e+000, 4.9e-324, 9.9e-324, 1.5e-323, 2.0e-323, 2.5e-323,
       3.0e-323, 3.5e-323, 4.0e-323, 4.4e-323, 4.9e-323, 5.4e-323])

更正数据类型

In [36]: y = np.frombuffer(astr, dtype=int)
In [37]: y
Out[37]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

添加形状:

In [38]: y.reshape((3,4))
Out[38]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

相关问题 更多 >