吴恩达机器学习 第三课 week3 强化学习(月球着陆器自动着陆)

news2024/11/18 21:30:30

目录

01 学习目标

02 概念

2.1 强化学习

2.2 深度Q学习(Deep Q-Learning )

03 问题描述

04 算法中的概念及原理 

05 月球着陆器自动着陆的算法实现

06 拓展:基于pytorch实现月球着陆器着陆

07 总结


写在最前:关于强化学习及lunar lander问题有很多技术贴,作者尚未理解透彻,不作全面深入的原理讲解,本文仅作吴恩达老师课程的课后代码实现之用途!

01 学习目标

     (1)理解什么强化学习

     (2)利用深度Q学习(Deep Q-Learning)算法实现月球着陆器自动着陆

02 概念

2.1 强化学习

       强化学习(Reinforcement Learning,简称RL)是一种机器学习方法,主要研究智能体(agent)如何在环境(environment)中采取行动以最大化某种累积奖励。在强化学习中,智能体通过与环境的交互来学习,即通过尝试不同的动作并观察结果,逐步优化其行为策略。

       强化学习的基本要素包括:

           1. 状态(State):描述环境当前情况的信息。
           2. 动作(Action):智能体可以执行的操作。
           3. 奖励(Reward):环境对智能体执行动作后的反馈,用于指导智能体的学习过程。
           4. 策略(Policy):智能体选择动作的规则或策略,可以是确定性的或概率性的。
           5. 价值函数(Value Function):评估状态或状态-动作对的好坏,通常用于指导策略的改进。
           6. 模型(Model):可选,表示环境的状态转移和奖励函数。

        强化学习的目标是找到一个最优策略,使得智能体在长期运行中获得的累积奖励最大化。常见的强化学习算法有Q-Learning、Deep Q-Networks (DQN)、Policy Gradients、SARSA、DDPG、PPO(近端策略优化算法)等。强化学习在游戏、机器人控制、自动驾驶、推荐系统等多个领域都有广泛的应用。例如,在AlphaGo中,深度强化学习被用来训练围棋AI,使其能够战胜世界顶级棋手。

2.2 深度Q学习(Deep Q-Learning )

       Deep Q-Learning 是一种强化学习方法,它将传统的 Q-Learning 的概念扩展到了使用深度神经网络来近似 Q 函数。在传统的 Q-Learning 中,Q 值通常是在一个表格中存储和更新的,这种方法在状态空间有限且较小的情况下效果很好。然而,对于高维状态空间或连续状态空间,表格方法不再可行,因为所需的存储量会变得非常庞大。而Deep Q-Learning 通过使用深度神经网络,也就是Deep Q-Network作为函数逼近器来克服这一限制。

DQN 有以下2个关键技术点:

    (1)经验回放(Experience Replay):DQN 使用经验回放缓冲区存储过去的经验(状态、动作、奖励、下一个状态),然后从中随机抽取一批数据来训练网络,这有助于打破数据的相关性,避免过度拟合最近的数据。

    (2)目标网络(Target Network):DQN 使用两个神经网络,一个是主网络(或在线网络),用于决策;另一个是目标网络,用于计算目标 Q 值。目标网络的参数定期从主网络同步过来,这样做是为了让目标 Q 值的计算更加稳定,避免训练过程中的振荡。

03 问题描述

       这是一个经典的强化学习案例,旨在让月球着陆器(Lunar Lander)通过算法自己学会如何安全地着陆到两面小旗中间的平台上。如下图所示:

04 算法中的概念及原理 

    先了解下动作空间(action space)和观察空间(obersevation space)的概念:什么是 Gym 中的观察空间(Observation Space)和动作空间(Action Space)?icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/658889348

    着陆器的动作空间包括4个动作:

0:什么都不做2:点火主引擎
1:点火左定向引擎3:点火右定向引擎

    着陆器的观察空间包括8个状态:

x:着陆器的 x 坐标θ:着陆器的角度
y:着陆器的 y坐标θ':着陆器的角速度
x':着陆器在 x 方向的线速度l:着陆器的左腿是否与地面接触(布尔值)
y':着陆器在 y 方向的线速度r:着陆器的右腿是否与地面接触(布尔值)

    奖励 Rewards的设计:

       每一步都会获得一个奖励。一个 episode(回合)总奖励是该 episode 中所有步骤的奖励之和。对于每一步,奖励如下:

      着陆器离着陆点越近/远,奖励增加/减少;

      着陆器移动越慢/快,奖励增加/减少;

      着陆器倾斜度越大,奖励减少;

      每个与地面接触的腿奖励增加10分;

      每帧侧引擎点火,奖励减少0.03分;

      每帧主引擎点火,奖励减少0.3分;

      episode 因坠毁或安全着陆而额外获得-100或+100分的奖励。

如果一个 episode 得分至少为200分,则训练停止。

       贝尔曼方程:

Q_{i+1}(s,a)=R+\gamma max_{a'}Q_i(s',a')

式中Q_{i+1}(s,a)动作-价值函数(action-value,Q函数), Q函数表示在给定状态 s下,采取动作 a后获得的期望累积回报。R为当前状态的奖励,γ为折扣因子,s'、a'表示下一个状态和动作。上式表示了agent在环境中总会选择奖励最大的动作,当执行动作次数足够多时(i→∞),Q就是最优解"Q(s,a;w)"。根据Q函数建立的神经网络称为“Q-network”,Q网络。

       算法的核心:

       算法中包含两个神经网络:一个是目标Q网络(target Q network)、另一个是主Q网络(Q network)。两个神经网络结构一样而参数不同,为“一前一后”关系,主Q网络更新快而目标Q网络更新慢。不断地训练“目标Q网络”与“主Q网络”,并通过控制两者间损失来可达到降低更新速度、增强稳定性的目的。每个回合结束计算两个Q之间的误差,如下:

Loss=[R+\gamma max_{a'}\hat{Q}(s',a';w')]-Q(s,a;w)

       每个回合结束agent会自动更新两个Q网络的参数,算法中为了agent表现稳定采用的“软更新”技术,如下式:

w'_{i+1}=\alpha w_i+(1-\alpha )w'_i

       式中,\alpha为学习率,一般设置为非常小的值。w'目标Q网络的参数,w主Q网络的参数。这样子,agent的目标Q网络的新参数w'_{i+1}、也就是新经验中,有一大部分是基于之前回合的旧经验w'_i而仅小部分来自最近一个回合学到的新经验w_i

05 月球着陆器自动着陆的算法实现

       (1)导包

import time
from collections import deque, namedtuple

import gymnasium as gym
#import gym
import numpy as np
import PIL.Image
import tensorflow as tf
import utils

from pyvirtualdisplay import Display
from pyglet.gl import gl
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.losses import MSE
from tensorflow.keras.optimizers import Adam

    (utils是吴恩达老师编写的计算模块,包括get_experiences、check_update_conditions、get_new_eps、get_action、update_target_network和plot_history等函数)

     (2)设置超参数

# 为TensorFlow设置随机种子
tf.random.set_seed(utils.SEED)
# 设置超参数
MEMORY_SIZE = 100_000     # 设置经验缓冲区的大小
GAMMA = 0.995             # 折扣因子
ALPHA = 1e-3              # 学习率
NUM_STEPS_FOR_UPDATE = 4  # 每4步执行一次学习更新

     (3)模拟环境

# 加载月球模拟环境
env = gym.make('LunarLander-v2', render_mode='rgb_array')

# 设置初始状态
env.reset()
PIL.Image.fromarray(env.render())

      LunarLander-v2是gym中模拟月球表面的虚拟环境。初始状态为agent位于显示窗口的中心顶部位置。运行以上代码,结果如下:

       (4)设置状态和动作

# 设置观察和动作变量
state_size = env.observation_space.shape
num_actions = env.action_space.n

# 获取初始状态
initial_state = env.reset()
# 选择第1个动作
action = 0

# step函数返回当前动作下的四个变量
next_state, reward, done, info, _= env.step(action)

print('State Shape:', state_size)
print('Number of actions:', num_actions)
with np.printoptions(formatter={'float': '{:.3f}'.format}):
    print("Initial State:",initial_state)
    print("Action:",action)
    print("Next State:", next_state)
    print("Reward Received:", reward)
    print("Episode Terminated:", done)
    print("Info:", info)

        运行以上代码,结果如下:

     

       在Open AI的Gym环境中,使用.step()方法来运行环境动态的单个时间步。在我们使用的gym版本中,.step()方法接受一个动作并返回五个值(最后1个为空):

      observation(object):在月球着陆器环境中,对应于包含着陆器位置和速度的numpy数组,即前面所说的观测空间的状态。

      reward (float):采取特定行动所获得的奖励。在月球着陆器环境中,对应于前面描述的奖励。

      done (bool):当done为True时,它表示回合结束,可以重置环境进行下一回合了。

      Info (dictionary):用于调试的诊断信息。算法中并没有使用这个变量。

     (5)神经网络

# 创建 主Q网络
q_network = Sequential([ 
    Input(shape=state_size),
    Dense(units=64,activation='relu', name='qL1'),
    Dense(units=64,activation='relu', name='qL2'),
    Dense(units=num_actions, name='qL3') 
    ])

# 创建目标 Q网络
target_q_network = Sequential([
    Input(shape=state_size),
    Dense(units=64,activation='relu', name='tqL1'),
    Dense(units=64,activation='relu', name='tqL2'),
    Dense(units=num_actions, name='tqL3')
    ])

optimizer = Adam(learning_rate=ALPHA)

      (6)经验回放

# 将经验存储为命名元组
experience = namedtuple("Experience", field_names=["state", "action", "reward", "next_state", "done"])

     (在Python中,namedtuplecollections模块中的一个函数,用于创建具有命名字段的小而简单的类。它非常适合用来创建只读的、轻量级的对象集合。Experience在这里被定义为一个namedtuple,用来存储智能体在环境中的经历,它有五个字段:state, action, reward, next_state, done

       定义损失函数:

def compute_loss(experiences, gamma, q_network, target_q_network):
    """ 
    损失函数
    
    Args:
      experiences: (tuple) 元组 ["state", "action", "reward", "next_state", "done"]
      gamma: (float) 折扣因子.
      q_network: (tf.keras.Sequential)  主Q网络,用于预测q_values
      target_q_network: (tf.keras.Sequential) 目标Q网络,用于预测y_targets
          
    Returns:
      loss: (TensorFlow Tensor(shape=(0,), dtype=int32)) 返回目标Q网络和主Q网络之间的均方误差.
    """
    
    # 返回经验
    states, actions, rewards, next_states, done_vals = experiences
    
    # 计算目标Q网络的最大值 max Q^(s,a)
    max_qsa = tf.reduce_max(target_q_network(next_states), axis=-1)
    # 贝尔曼方程计算目标Q网络的值
    y_targets = rewards + gamma * max_qsa * (1 - done_vals)
    
    # 获得主Q网络估计值 q_values
    q_values = q_network(states)
    q_values = tf.gather_nd(q_values, tf.stack([tf.range(q_values.shape[0]),
                                                tf.cast(actions, tf.int32)], axis=1))
        
    # 计算loss 
    loss = MSE(y_targets, q_values)
    
    return loss

      (7)更新网络参数

@tf.function  # 装饰器,可以将Python函数转换为TensorFlow图结构,函数中的所有操作都会在TensorFlow图中执行
def agent_learn(experiences, gamma):
    """
    更新Q网络的权重参数.
    
    Args:
      experiences: (tuple) 元组["state", "action", "reward", "next_state", "done"]
      gamma: (float) 折扣因子.
    
    """
    
    # 计算损失函数
    with tf.GradientTape() as tape:
        loss = compute_loss(experiences, gamma, q_network, target_q_network)

    # 计算梯度
    gradients = tape.gradient(loss, q_network.trainable_variables)
    
    # 更新主Q网络的权重参数
    optimizer.apply_gradients(zip(gradients, q_network.trainable_variables))

    # 更新目标Q网络的权重参数
    utils.update_target_network(q_network, target_q_network)

       (8)训练智能体(agent)

start = time.time()   # 开始计时

num_episodes = 2000        # 训练回合总数
max_num_timesteps = 1000   # 每个回合训练步数

total_point_history = []

num_p_av = 100    # number of total points to use for averaging
epsilon = 1.0     # ε-greedy策略的初始值

# 创建经验缓冲区
memory_buffer = deque(maxlen=MEMORY_SIZE)

# target Q network的初始权重参数设置为与Q-Network相同
target_q_network.set_weights(q_network.get_weights())

for i in range(num_episodes):
    
    # 每个回合开始时,重设环境得到初始状态
    state = env.reset()[0]
    total_points = 0
    
    for t in range(max_num_timesteps):
        
        # 使用ε-greedy策略,在当前状态s选择一个动作a
        state_qn = np.expand_dims(state, axis=0)
        q_values = q_network(state_qn)
        action = utils.get_action(q_values, epsilon)
        
        # 计算采取当前动作a可得到的奖励r,及下个状态s'
        next_state, reward, done, info, _ = env.step(action)
        
        # 储存经验元组 (S,A,R,S')至经验缓冲区
        memory_buffer.append(experience(state, action, reward, next_state, done))
        
        # 通过当前步数和缓冲区数据量判别是否达到更新条件
        update = utils.check_update_conditions(t, NUM_STEPS_FOR_UPDATE, memory_buffer)
        
        if update:
            # 随机选取经验样本
            experiences = utils.get_experiences(memory_buffer)
            
            # 梯度下降法更新网络参数
            agent_learn(experiences, GAMMA)
        
        state = next_state.copy()
        total_points += reward
        
        if done:
            break
            
    total_point_history.append(total_points)
    av_latest_points = np.mean(total_point_history[-num_p_av:])
    
    # 更新ε
    epsilon = utils.get_new_eps(epsilon)

    print(f"\rEpisode {i+1} | Total point average of the last {num_p_av} episodes: {av_latest_points:.2f}", end="")

    if (i+1) % num_p_av == 0:
        print(f"\rEpisode {i+1} | Total point average of the last {num_p_av} episodes: {av_latest_points:.2f}")

    # 如果最近100个回合的平均分超过200分,停止训练
    if av_latest_points >= 200.0:
        print(f"\n\nEnvironment solved in {i+1} episodes!")
        q_network.save('lunar_lander_model.keras')
        break
        
tot_time = time.time() - start

print(f"\nTotal Runtime: {tot_time:.2f} s ({(tot_time/60):.2f} min)")

# Plot the point history
utils.plot_history(total_point_history)

        运行以上代码,结果如下:

     

        (9)训练过程保存为视频

import logging
import imageio
import base64
import IPython

logging.getLogger().setLevel(logging.ERROR)


def create_video(filename, env, q_network, fps=30):
    with imageio.get_writer(filename) as video:
        done = False
        state = env.reset()[0]
        frame = env.render()
        #frame = env.render(mode="rgb_array")
        video.append_data(frame)
        while not done:    
            state = np.expand_dims(state, axis=0)
            q_values = q_network(state)
            action = np.argmax(q_values.numpy()[0])
            state, _, done, _, _ = env.step(action)
            frame = env.render()
            frame = PIL.Image.fromarray(frame)
            video.append_data(frame)


def embed_mp4(filename):
    """Embeds an mp4 file in the notebook."""
    video = open(filename,'rb').read()
    b64 = base64.b64encode(video)
    tag = '''
    <video width="840" height="480" controls>
    <source src="data:video/mp4;base64,{0}" type="video/mp4">
    Your browser does not support the video tag.
    </video>'''.format(b64.decode())
    return IPython.display.HTML(tag)


filename = "./videos/lunar_lander.mp4"
create_video(filename, env, q_network)
embed_mp4(filename)

最后一步,我这里保存视频失败,生成的视频打不开,哪位大佬知道原因的可以在评论区解答下!

 06 拓展:基于pytorch实现月球着陆器着陆

        由于拿到吴恩达老师课程的代码后,折腾几天都跑不通,终于能跑了又不能生成视频,就先找了个大神的pytorch代码跑了下,可以正常训练和保存视频,基于tensorflow和pytorch的步骤都是一样的。链接放在下面:

【机器学习】强化学习(六)-DQN(Deep Q-Learning)训练月球着陆器示例-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/cxyhjl/article/details/135812771

07 总结

    (1)强化学习的高级之处在于:只需给定目标、设置好奖励机制,agent就可以自主学习完成任务,特斯拉最新的Optimus机器人身上就采用了强化学习。

    (2)强化学习实现着陆器着陆月球的主要内容包括:超参数、虚拟环境、两个Q神经网络、经验重放缓冲区、epsilon贪婪策略、软更新、训练agent,前6块内容柔和进了最后一步“训练agent”中,强化学习中很重要的奖励设置本文没有涉及,因为lunar lander的奖励机制在采用的env.step()方法中.。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1899805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

封锁-封锁模式(共享锁、排他锁)、封锁协议(两阶段封锁协议)

一、引言 1、封锁技术是目前大多数商用DBMS采用的并发控制技术&#xff0c;封锁技术通过在数据库对象上维护锁来实现并发事务非串行调度的冲突可串行化 2、基于锁的并发控制的基本思想是&#xff1a; 当一个事务对需要访问的数据库对象&#xff0c;例如关系、元组等进行操作…

python-21-零基础自学python 写了一个彩票 发现买彩票中了真的是天选

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版 知识点&#xff1a; from random import choice、choice&#xff08;&#xff09;函数用法、while循环 练习内容&#xff1a; 练习9-14&#xff1a;彩票 创建一个列表或元组&#xff0c;其中包含10个数…

算法体系-26 第二十六节:第26节:单调栈结构 (5节)

一 单调栈知识讲解 1.1描述 一个数组里面想的到每个位置与他最近的左边和右边比他小的最近的信息 1.2 分析 通过单调栈的特点&#xff0c;for遍历数组中的每个数&#xff0c;当前数来的时候对比单调栈中的数进行每个数的左右判断完满足条件的进行更新到当前i种的 int[][] re…

S32DS S32 Design Studio for S32 Platform 3.5 窗口多开模式

前言 NXP S32系列的芯片&#xff0c;开发默认使用 S32DS&#xff0c;也就是 S32 Design Studio for S32 Platform&#xff0c;当前版本 S32 Design Studio for S32 Platform 3.5&#xff0c;初步体验像是使用 eclipse&#xff0c;作为代码集成开发环境&#xff0c;比如代码阅读…

Hadoop权威指南-读书笔记-02-关于MapReduce

Hadoop权威指南-读书笔记 记录一下读这本书的时候觉得有意思或者重要的点~ 还是老样子~挑重点记录哈&#x1f601;有兴趣的小伙伴可以去看看原著&#x1f60a; 第二章 关于MapReduce MapReduce是一种可用于数据处理的编程模型。 MapReduce程序本质上是并行运行的&#xff0c…

bert-base-chinese模型离线使用案例

import torch import torch.nn as nn from transformers import BertModel, BertTokenizer# 通过torch.hub(pytorch中专注于迁移学的工具)获得已经训练好的bert-base-chinese模型 # model torch.hub.load(huggingface/pytorch-transformers, model, bert-base-chinese) model…

Vivado FFT IP核使用

1. 今日摸鱼任务 学习Vivado FFT IP核的使用 Vivado_FFT IP核 使用详解_vivado fft ip核-CSDN博客 这篇写的很详细啦 简单做一点笔记进行记录 2. FFT IP核 xfft_0 ff (.aclk(aclk), // input wire aclk.aresetn(aresetn)…

Oracle Database 23ai新特性:增加聚合函数对INTERVAL数据类型支持

在Oracle早期的版本&#xff0c;聚合函数和分析函数MIN/MAX 就支持了INTERVAL 数据类型。但是&#xff0c;当我们使用SUM或AVG函数对INTERVAL 数据类型进行运算时&#xff0c;就会报错。 随着Oracle Database 23ai 的发布&#xff0c;增加了 AVG 以及 SUM 函数对INTERVAL 数据…

SQL 汇总各个部门当前员工的title类型的分配数目

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 有一个部门表…

Python实现ABC人工蜂群优化算法优化卷积神经网络分类模型(CNN分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 人工蜂群算法(Artificial Bee Colony, ABC)是由Karaboga于2005年提出的一种新颖的基于群智能的全局优化…

每日一更 EFK日志分析系统

需要docker和docker-compose环境 下面时docker-compose.yaml文件 [rootnode1 docker-EFK]# cat docker-compose.yaml version: 3.3services:elasticsearch:image: "docker.elastic.co/elasticsearch/elasticsearch:7.17.5"container_name: elasticsearchrestart: …

【python】PyQt5可视化开发,如何设计鼠标显示的形状?

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Java 面向对象编程(OOP)的四大特征

Java 面向对象编程&#xff08;OOP&#xff09;的四大特征 1、抽象2、继承3、 封装4、多态性 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java编程中&#xff0c;面向对象编程&#xff08;OOP&#xff09;是一个核心概念。OOP的四大基…

Cgi上传文件 注意事项

//核心代码 ofstream outfile("/opt/software/" file.getFilename(), ios::out | ios::binary); outfile << file.getData(); //错误方式&#xff1a;outfile << file.getData() <<endl; outfile.close(); 参考博客&#xff1a; https://blog.cs…

设计模式探索:代理模式

1. 什么是代理模式 定义 代理模式是一种结构型设计模式&#xff0c;通过为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和实际对象之间起到中介作用&#xff0c;可以在不改变真实对象的情况下增强或控制对真实对象的访问。 目的 代理模式的主要目的是隐…

基于深度学习的软件漏洞检测模型在现实数据集上的表现

软件漏洞对日常软件系统的影响令人担忧。尽管已经提出了基于深度学习模型的漏洞检测方法&#xff0c;但这些模型的可靠性仍然是一个重大问题。先前的评估报告这些模型具有高达99%的召回率/F1分数&#xff0c;但研究发现&#xff0c;这些模型在实际应用场景下的表现并不佳&#…

【Python系列】数字的bool值

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【Qwen2部署实战】Ollama上的Qwen2-7B:一键部署大型语言模型指南

系列篇章&#x1f4a5; No.文章1【Qwen部署实战】探索Qwen-7B-Chat&#xff1a;阿里云大型语言模型的对话实践2【Qwen2部署实战】Qwen2初体验&#xff1a;用Transformers打造智能聊天机器人3【Qwen2部署实战】探索Qwen2-7B&#xff1a;通过FastApi框架实现API的部署与调用4【Q…

Java | Leetcode Java题解之第218题天际线问题

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> getSkyline(int[][] buildings) {PriorityQueue<int[]> pq new PriorityQueue<int[]>((a, b) -> b[1] - a[1]);List<Integer> boundaries new ArrayList&l…

FIND_IN_SET使用案例--[sql语句根据多ids筛选出对应数据]

一 FIND_IN_SET select id,system_ids from intellect_client_info where FIND_IN_SET(5, system_ids) > 0;