Keras predict in a process freezes - python-3.x

I am trying to make an server which predicts (regression) given a certain input, however when I make a shared keras (with tensorflow backend) file to preload and skip loading the model every time (which would save about 1.8 seconds), and when I try to predict anything from a thread the program just freezes (even though only one thread is accessing it during my test). I know that the tensor is not made for this, however as it is only predicting there should be a workaround for this. I have tried using _make_prediction_function but that did not work.
This is the main function:
keras_model = keras_model_for_threads()
def thread_function(conn, addr, alive):
print('Connected by', addr)
start = time.time()
sent = conn.recv(1024)
x_pred = preproc(sent)
conn.sendall(keras_model.predict_single(x_pred))
conn.close()
import socket
HOST = ''
PORT = xxxxx
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1000)
print('Ready for listening')
while alive.get():
conn, addr = s.accept()
Process(target=thread_function, args=(conn, addr, alive)).start()
with the keras_model:
class keras_model_for_threads():
def __init__(self):
self.model = load_model(model_path)
self.model._make_predict_function()
def predict_single(self, x_pred):
return self.model.predict(x_pred)
Now if I run this normally, it executes and returns a prediction but through the Process with the thread function it freezes on the self.model.predict.

After some more searching I found an answer which works, namely making a manager to handle the prediction. This changes the original keras code to:
from multiprocessing.managers import BaseManager
from multiprocessing import Lock
class KerasModelForThreads():
def __init__(self):
self.lock = Lock()
self.model = None
def load_model(self):
from keras.models import load_model
self.model = load_model(model_path)
def predict_single(self, x_pred):
with self.lock:
return (self.model.predict(x_pred) + self.const.offset)[0][0]
class KerasManager(BaseManager):
pass
KerasManager.register('KerasModelForThreads', KerasModelForThreads)
And the main code to
from keras_for_threads import KerasManager
keras_manager = KerasManager()
keras_manager.start()
keras_model = keras_manager.KerasModelForThreads()
keras_model.load_model()
def thread_function(conn, addr, alive):
print('Connected by', addr)
start = time.time()
sent = conn.recv(1024)
x_pred = preproc(sent)
conn.sendall(keras_model.predict_single(x_pred))
conn.close()
import socket
HOST = ''
PORT = xxxxx
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1000)
print('Ready for listening')
while alive.get():
conn, addr = s.accept()
Process(target=thread_function, args=(conn, addr, alive)).start()
This is a stripped down version (without the Flask stuff, just the keras part) from the github project I found here:https://github.com/Dref360/tuto_keras_web

Related

asyncio concurrently my code does not work properly

I am trying to run two threads concurrently in order to: collect data and save this data periodically. I am using socket to collect the data and module asyncio in order to run in parallel this two functions.
This is the code:
# IMPORT LIBRARIES:
import socket
import asyncio
# DEFINITION FUNCTION:
async def restart_variable():
print("executes restart_variable")
while True:
await asyncio.sleep(20)
print("Should clean and save data")
print("For the moment only clean")
totaldata = ""
async def collect_data():
print("executes collect data")
totaldata = ""
while True:
data = sock.recv(1024)
data = str(data, "utf-8")
totaldata += data
print(1, len(totaldata))
print(2, data)
async def main():
try:
sock.connect((HOST, PORT))
print("Connected")
except Exception as e:
print("Cannot connect to the server:", e)
try:
asyncio.gather(restart_variable(), collect_data())
except KeyboardInterrupt:
print("Manually interrupted")
sock.close()
except Exception as e:
print(e)
sock.close()
HOST = "HOST"
PORT = 2304
# MAIN EXECUTION:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
asyncio.run(main())
However, only collect data is working. restart_variable function is only executed one time. I dont understand why while True has no effect.

Why won't my python script start a server on port 36296?

I wrote a python script to start a server on port 36296 but it doesn't work at all, what went wrong here? When I tried to connect to port 36296, it said connection failed: connection refused. Please help explain why it is malfunctioning in such a peculiar way. Thank you. (I have tried this many times in many ways for a long time, so help would be EXTREMELY appreciated.)
import sys, time, logging, os, argparse
import numpy as np
from PIL import Image, ImageGrab
from socketserver import TCPServer, StreamRequestHandler
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
from train import create_model, is_valid_track_code, INPUT_WIDTH,
INPUT_HEIGHT, INPUT_CHANNELS
def prepare_image(im):
im = im.resize((INPUT_WIDTH, INPUT_HEIGHT))
im_arr = np.frombuffer(im.tobytes(), dtype=np.uint8)
im_arr = im_arr.reshape((INPUT_HEIGHT, INPUT_WIDTH, INPUT_CHANNELS))
im_arr = np.expand_dims(im_arr, axis=0)
return im_arr
class TCPHandler(StreamRequestHandler):
def handle(self):
if args.all:
weights_file = 'weights/all.hdf5'
logger.info("Loading {}...".format(weights_file))
model.load_weights(weights_file)
logger.info("Handling a new connection...")
for line in self.rfile:
message = str(line.strip(),'utf-8')
logger.debug(message)
if message.startswith("COURSE:") and not args.all:
course = message[7:].strip().lower()
weights_file = 'weights/{}.hdf5'.format(course)
logger.info("Loading {}...".format(weights_file))
model.load_weights(weights_file)
if message.startswith("PREDICTFROMCLIPBOARD"):
im = ImageGrab.grabclipboard()
if im != None:
prediction = model.predict(prepare_image(im), batch_size=1)[0]
self.wfile.write((str(prediction[0]) + "\n").encode('utf-8'))
else:
self.wfile.write("PREDICTIONERROR\n".encode('utf-8'))
if message.startswith("PREDICT:"):
im = Image.open(message[8:])
prediction = model.predict(prepare_image(im), batch_size=1)[0]
self.wfile.write((str(prediction[0]) + "\n").encode('utf-8'))
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Start a prediction server that other apps will call into.')
parser.add_argument('-a', '--all', action='store_true', help='Use the combined weights for all tracks, rather than selecting the weights file based off of the course code sent by the Play.lua script.', default=False)
parser.add_argument('-p', '--port', type=int, help='Port number', default=36296)
parser.add_argument('-c', '--cpu', action='store_true', help='Force Tensorflow to use the CPU.', default=False)
args = parser.parse_args()
if args.cpu:
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
logger.info("Loading model...")
model = create_model(keep_prob=1)
if args.all:
model.load_weights('weights/all.hdf5')
logger.info("Starting server...")
server = TCPServer(('0.0.0.0', args.port), TCPHandler)
print("Listening on Port: {}".format(server.server_address[1]))
sys.stdout.flush()
server.serve_forever()

TypeError: Cannot interpret feed_dict key as Tensor

I am using threading method to make multiple client to one server. I am using a pretrained model with resnet50 to predict something.
My prediction code is
def prediction(array):
array = np.array(array , dtype = np.float64)
array = np.reshape(array, (1,224,224,3))
#print(array.shape)
a = preprocess_input(array)
model = ResNet50(weights='imagenet', include_top=False)
features = model.predict(a)
#print(features.shape)
image = features.reshape(features.shape[0] , -1)
#print(image.shape)
loaded_model = keras.models.load_model('RESNET50.h5')
y_predict = loaded_model.predict(image)
if y_predict[0][0] > y_predict[0][1]:
return "Non-Nude"
else:
return "Nude"
K.clear_session()
and my server code is this
class ClientThread(Thread):
def __init__(self,ip,port,sock):
Thread.__init__(self)
self.ip = ip
self.port = port
self.sock = sock
print("New thread started for "+ip+":"+str(port))
def run(self):
send_one_message(self.sock, self.ip)
send_one_message(self.sock, self.port)
data = recv_one_message(self.sock)
#print("data recevied")
res = prediction(data)
send_one_message(self.sock, res)
TCP_IP = ''
TCP_PORT = 12001
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(5)
print("Waiting for incoming connections...")
(conn, (ip,port)) = tcpsock.accept()
print('Got connection from ', (ip,port))
newthread = ClientThread(ip,port,conn)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
It is able to connect multiple clients but it give fine prediction only for first client connected and for every another client it throws an error as
thanks for your help!

Stop server from client's thread / Modify server's variable from client's thread

I would like to write an application that could stop the server based on client's input. The server is multi-threaded and I do not understand how can I do this.
Basically, I described my problem here: Modify server's variable from client's thread (threading, python).
However, this is the Python solution, not the general solution I could implement in Java, C, C++, etc.
I need to close other clients, when one of them guesses the number, but the server should be still alive, ready for the new game.
Can I ask for some advices, explanations?
I tried this (still do not know how to port it to C or Java), but it lets the clients send the numbers even if one of them just guesses it. It seems to me that kill_em_all does not do it's job, it does not close all the connections and does not disconnect the other clients as it should. How to improve this?
#!/usr/bin/env python
from random import randint
import socket, select
from time import gmtime, strftime
import threading
import sys
class Handler(threading.Thread):
def __init__(self, connection, randomnumber, server):
threading.Thread.__init__(self)
self.connection = connection
self.randomnumber = randomnumber
self.server = server
def run(self):
while True:
try:
data = self.connection.recv(1024)
if data:
print(data)
try:
num = int(data)
if self.server.guess(num) :
print 'someone guessed!'
self.server.kill_em_all()
break
else :
msg = "Try again!"
self.connection.sendall(msg.encode())
except ValueError as e:
msg = "%s" % e
self.connection.sendall(msg.encode())
else:
msg = "error"
self.connection.send(msg.encode())
except socket.error:
break
self.connection.close()
def send(self, msg):
self.connection.sendall(msg)
def close(self):
self.connection.close()
class Server:
randnum = randint(1,100)
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.address = (self.ip, self.port)
self.server_socket = None
def guess(self, no):
if self.randnum == no:
self.randnum = randint(1, 100)
print("New number is ", self.randnum )
result = True
else:
result = False
return result
def kill_em_all(self):
for c in self.clients:
c.send("BYE!")
c.close()
def run(self):
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((self.ip, self.port))
self.server_socket.listen(10)
self.clients = []
print('Num is %s' % self.randnum)
while True:
connection, (ip, port) = self.server_socket.accept()
c = Handler(connection, self.randnum, self)
c.start()
self.clients.append(c)
except socket.error as e:
if self.server_socket:
self.server_socket.close()
sys.exit(1)
if __name__ == '__main__':
s = Server('127.0.0.1', 7777)
s.run()
Client code:
import socket
import sys
port = 7777
s = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
s.connect(('127.0.0.1', port))
except socket.error, (value, message):
if s:
s.close()
print "Could not open socket: " + message
sys.exit(1)
while True:
data = raw_input('> ')
s.sendall(data)
data = s.recv(1024)
if data:
if data == "BYE!":
break
else:
print "Server sent: %s " % data
s.close()
Log in. Using whatever protocol you have, send the server a message telliing it to shut down. In the server, terminate your app when you get the shutdown message. That's it. It's not a problem with any OS I have used - any thread of a process can terminate that process.

force socket to timeout in python

I'm using a socket to listen on a port in a while loop, with a 5 second timeout set by socket.settimeout(). But I have another method, which set's the listening port, and when called with a new port, i wanna force the socket to timeout so that I can reinitialise the socket and set the appropriate port inside the while loop. Is there a way to do that?
The socket is inside a subclass of threading.Thread
PS. Since this is my second day with Python, any other suggestions regarding any part would be most welcome. Thank you
EDIT:
I almost forgot. I want to reinitialise the socket when the setoutboundport method is called.
EDIT2
Man the whole code is messed up. I reexamined everything and it's really wrong for what I wanna achieve. Just focus on the main question. Timing out the socket.
import threading
import socket
import ResponseSender
import sys
import traceback
def __init__(self, inboundport, outboundip, outboundport, ttl=60):
super(Relay, self).__init__()
self.inboundport = inboundport
self.outboundip = outboundip
self.outboundport = outboundport
self.ttl = ttl
self.serverOn = True
self.firstpacket = True
self.sibling = None
self.newoutboundport = 0
self.listener = None
# ENDOF: __init__
def stop(self):
self.serverOn = False
# ENDOF: stop
def setsiblingrelay(self, relay):
self.sibling = relay
# ENDOF: setsiblingrelay
def setoutboundport(self, port):
self.newoutboundport = port
# ENDOF: setoutboundport
def run(self):
s = None
try:
while self.serverOn:
if not s:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
if self.outboundport != self.newoutboundport:
try:
s.close()
except:
pass
s.settimeout(4)
s.bind(('', self.inboundport))
print("Relay started :{0} => {1}:{2}".format(self.inboundport, self.outboundip, self.outboundport))
print("---------------------------------------- LISTENING FOR INCOMING PACKETS")
data, address = s.recvfrom(32768)
print("Received {0} from {1}:{2} => sending to {3}:{4}"
.format(data, address[0], address[1], self.outboundip, self.outboundport))
ResponseSender.sendresponse(address[0], address[1], data)
except TimeoutError:
pass
except:
print("Error: {0}".format(traceback.format_exception(*sys.exc_info())))
# ENDOF: run

Resources