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
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.
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()
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!
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.
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