精华内容
下载资源
问答
  • java 传递参数两种方式

    万次阅读 多人点赞 2015-10-19 15:39:28
    Java中没有指针,所以也没有引用传递了,仅仅值传递不过可以通过对象的方式来实现引用传递 类似java没有多继承 但可以用多次implements 接口实现多继承的功能  值传递:方法调用时,实际参数把它的值传递给对应...

     

    Java中没有指针,所以也没有引用传递了,仅仅有值传递不过可以通过对象的方式来实现引用传递 类似java没有多继承 但可以用多次implements 接口实现多继承的功能

     

      值传递:方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值。

      引用传递:也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。

     

           a.传递值的数据类型:八种基本数据类型和String(这样理解可以,但是事实上String也是传递的地址,只是string对象和其他对象是不同的,string对象是不能被改变的,内容改变就会产生新对象。那么StringBuffer就可以了,但只是改变其内容。不能改变外部变量所指向的内存地址)。
        b.传递地址值的数据类型:除String以外的所有复合数据类型,包括数组、类和接口 
    值传递的例子:
    package com.other.test;
    
    public class Test {
    	public static void change(int i, int j) { 
    		int temp = i; 
    		i = j; 
    		j = temp;
    	} 
    
    	public static void main(String[] args) { 
    		int a = 3; 
    		int b = 4; 
    		change(a, b); 
    		System.out.println("a=" + a); 
    		System.out.println("b=" + b);
    	}
    }
    
    

    输出的结果是 a=3 b=4,传递的值并不会改变原值
     
    引用传递的例子:(数组)
    package com.other.test;
    
    public class Test {
    	public static void change(int[] counts) { 
    		counts[0] = 6; 
    		System.out.println(counts[0]);
    	} 
    
    	public static void main(String[] args) { 
    		int[] count = { 1, 2, 3, 4, 5 }; 
    		change(count);
    		System.out.println(count[0]);
    	} 
    }

    输出结果是6 6 也就是引用的值改变了原来的值
     
    引用传递的例子:(对象)
     
    定义一个A对象:
     
    package com.other.test;
    
    public class A {
    	int i = 0;
    }


    对上边对象操作的类:

     

     

    package com.other.test;
    
    public class Test {
    	public static void add(A a) { 
    		//a = new A();   ①
    		a.i++;
    	} 
    
    	public static void main(String args[]) { 
    		A a = new A(); 
    		add(a); 
    		System.out.println(a.i );
    	} 
    }
    


    当把①注解掉时,输出的结果是1,当①没有注解是是0,原因是 a =new A();构造了新的A对象就不是传递的那个对象了。

     

    看看String的情况:

     

    package com.other.test;
    
    public class Test {
    	String str = new String("old"); 
    	char[] ch = { 'a', 'b', 'c' }; 
    	public static void main(String args[]) { 
    		Test ex = new Test(); 
    		ex.change(ex.str, ex.ch); 
    		System.out.print(ex.str + " and "); 
    		System.out.println(ex.ch);
    	} 
    
    	public void change(String str, char ch[]) { 
    		str = "new"; 
    		ch[0] = 'd';
    	}
    }


    输出的结果的是 old and dbc也就是传递String并不会改变原值,而是创建了一个新值。 ch[]就是一个简单的数组的传递。

     

    ( 对象包括对象引用即地址和对象的内容)

    String 比较特别,看过String 代码的都知道, String 是 final的。所以值是不变的。 函数中String对象引用的副本指向了另外一个新String对象,而数组对象引用的副本没有改变,而是改变对象中数据的内容. 
      对于对象类型,也就是Object的子类,如果你在方法中修改了它的成员的值,那个修改是生效的,方法调用结束后,它的成员是新的值,但是如果你把它指向一个其它的对象,方法调用结束后,原来对它的引用并没用指向新的对象。 
      Java参数,不管是原始类型还是引用类型,传递的都是副本(有另外一种说法是传值,但是说传副本更好理解吧,传值通常是相对传址而言)。 
      如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的值不会改变原始的值.
      如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的值,那么在函数内的改变会影响到传入的参数。如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的地址,所以不会改变参数的值。

    关注我,获取400个的赚钱金点子,轻松开启副业生涯

    美团招聘,有意向的私信我

    岗位名称:美团到家事业群-外卖技术部-JAVA高级工程师
    职级要求:P2-3~P3-2

    岗位职责:
    - 负责上单业务系统的开发工作,深入理解业务痛点,通过技术手段满足并促进业务快速发展需要;
    - 参与系统需求分析与设计,快速响应业务需求,负责完成核心代码编写,接口规范制定;
    - 参与解决项目中的重难点问题,针对复杂业务模型能够给出合理的解决方案;

    岗位基本要求:
    - 参与过大型复杂分布式互联网系统的设计,要求有复杂业务的开发经验和较强的逻辑/概率思维能力,善于分析、归纳、描述、沟通和解决问题;
    - 本科及以上学历,扎实的计算机基础,4年及以上工作经验,长期使用Java及开源框架进行项目开发,并有一定的项目管理经验;
    - 深入使用Java,熟悉掌握常用的Java类库及框架,如多线程、并发处理、I/O与网络通讯等,对Java虚拟机有较深了解;
    - 擅长使用开源框架,在某个领域内对开源框架有一定的审美,做过选型研究,解读过部分或者全部源码,掌握实现原理;
    - 精通 MySQL 应用开发,熟悉数据库原理和常用性能优化技术,以及 NoSQL,Queue 的原理、使用场景以及限制;
    - 研究过 http 协议、搜索引擎、缓存、jvm 调优、序列化、nio、RPC 调用框架等,并且有相关实践经验;
    - 有强烈的责任心和团队合作精神,良好的抗压能力,心态积极,能主动融入团队;

    具备以下者优先:
    - 参与过相关系统建设;
    - 有高并发系统经验;
    - 参与过开源工作;
    - 有代码洁癖、有极客精神;

    展开全文
  • Hyperopt 参数优化

    万次阅读 多人点赞 2018-08-28 20:02:03
    Hyperopt(Hyper-parameter Optimization)用于模型选择和参数优化参数选择在训练模型时是一个很关键的部分。然而存在这样的问题,一方面参数选择背后包含着一定的数学原理,对于新手来说难上手;另一方面,一个...

    翻译自https://districtdatalabs.silvrback.com/parameter-tuning-with-hyperopt
    Parameter Tuning with Hyperopt –Kris Wright

    概述

    Hyperopt可以帮助快速进行机器学习模型参数调试。通常情况下有两种类型的参数调试方法,网格搜索(grid search)和随机搜索(random search)。网格搜索速度慢但是适用于需要随整个参数空间进行搜索的情况;随机搜索速度很快但是容易遗漏一些重要信息。幸运的是,我们有第三个选择:贝叶斯优化(Bayesian optimization)。这里我们关注贝叶斯优化在Python中的实现:Hyperopt模块。

    使用贝叶斯优化进行参数调试允许我们获得给定模型的最优参数,如,逻辑回归( logistic regression),因此我们可以进行最优模型选择。通常情况下,机器学习工程师或数据科学家会对一些模型进行一些形式的手动参数调试(如网格搜索或随机搜索),如决策树(decision tree)、支持向量机(support vector machine)、k最近邻(k nearest neighbors)-然后比较准确度得分(accuracy score)进而选择性能表现最好的一组参数给模型使用。这种方法可能会产生次优模型(sub-optimal models)。数据科学家可能会给决策树选择一组最优参数,但是对SVM却不是最优的,这就意味着模型比较是有缺陷的。KNN每次都可以打败SVM,如果SVM的参数选择很差的话。贝叶斯优化允许数据科学家找到所有模型的最优参数,然后比较所有使用了最佳参数的模型。这样的话,在模型选择中,就可以比较最优的决策树和最优的支持向量机。只有这样才能保证我们选择和使用了实际最好的模型。

    本文涉及的主题包括:
    - 评估函数(Objective functions)
    - 搜索空间(Search spaces)
    - 存储评价试验(Storing evaluation trials)
    - 可视化(Visualization)
    - 鸢尾花数据集实例(Full example on a classic dataset: Iris)

    目标函数(Objective Functions - A Motivating Example)

    假设有一个定义在摸个范围内的函数,你想要使这个函数最小化,也就是说,你想要找到一个输入值,使得函数的输出结果是最小的。如下面的例子,找到一个x,使得线性函数y(x)=x取得最小值。

    from hyperopt import fmin, tpe, hp
    best = fmin(
        fn=lambda x: x,
        space=hp.uniform('x', 0, 1),
        algo=tpe.suggest,
        max_evals=100)
    print best

    下面进行分解说明。
    函数fmin首先要接收一个函数fn来最小化,这里我们指定fn为一个匿名函数lambda x: x,实际上这个函数可以是任何有效的带有返回值的函数(valid value-returning function),如回归中的平均绝对误差(mean absolute error)。
    第二个参数space指定了搜索空间(search space),在这个例子中为在0到1范围之间的数字。hp.uniform是一个内置的( built-in)hyperopt函数,包括三个参数:name:x,范围的上界和下届:0和1。
    参数algo接收一个搜索算法(serach algorithm),这个例子中tpe代表tree of Parzen estimators。这个话题超出了这个博客文章的范围,更多关于tpe的内容请参考这里。algo参数也可以设置成hyperopt.random,但我们在此不做介绍,因为这是众所周知的搜索策略。

    最后,我们指定fmin函数执行的最大次数max_evals。fmin函数返回一个python字典。函数输出的一个例子:{‘x’: 0.000269455723739237}。
    下面是一张函数图像,红色的点是我们要找的x的位置。
    y=x

    另一个例子(More Complicated Examples)

    这里有个更复杂的目标函数:lambda x: (x-1)**2,这次我们试着最小化一个二次方程y(x)=(x1)2。因此,我们将搜索空间更改为包括我们已经知道的最优值x=1以及加上两侧的一些次优范围:hp.uniform(‘x’, -2, 2)。
    我们可以得到:

    best = fmin(
        fn=lambda x: (x-1)**2,
        space=hp.uniform('x', -2, 2),
        algo=tpe.suggest,
        max_evals=100)
    print best

    输出为:

    {'x': 0.997369045274755}

    函数如下图:
    y=(x-1)^2
    除了最小化目标函数,也许我们想使函数值最大化。这种情况下我们只需要返回函数的负值,如函数y(x) = -(x**2):
    y=-x^2
    如何解决这个问题呢?我们只需要将目标函数改为lambda x: (x**2),求y(x) = -(x**2)得最小值即为求y(x) = -(x**2)的最大值。
    同理对于刚开始的线性函数的例子,我们将求最小化改为求最大化,将将目标函数改为lambda x: -x即可。
    下面是一个有用许多(给定无穷范围的无穷多个)局部最小值得函数,也可以求最大值。
    y=sin(x)/x

    搜索空间(Search spaces)

    Hyperopt模块包含了一些方便的函数(handy functions)来指定输入参数的范围。我们已经见过hp.uniform。最初,这些是随机搜索空间,但是随着hyperopt的学习(随着从目标函数获得更多的feedback),它会对初始搜索空间的不同部分进行调整和采样,并认为这些部分会给它提供最有意义的反馈。
    以下函数将在本文使用:

    • hp.choice(label, options) ,其中options为 python list 或tuple
    • hp.normal(label, mu, sigma) ,其中mu 和 sigma 分别为均值和标准差
    • hp.uniform(label, low, high),其中low和 high分别为范围的上界和下界

    其他还有hp.normal, hp.lognormal, hp.quniform,因为本文不会使用就没有写,可自行了解。
    下面定义搜索空间:

    import hyperopt.pyll.stochastic
    
    space = {
        'x': hp.uniform('x', 0, 1),
        'y': hp.normal('y', 0, 1),
        'name': hp.choice('name', ['alice', 'bob']),
    }
    
    print hyperopt.pyll.stochastic.sample(space)

    例子输出:

    {'y': -1.4012610048810574, 'x': 0.7258615424906184, 'name': 'alice'}

    获取信息和试验(Capturing Info with Trials)

    如果能看到hyperopt黑盒里到底发生了什么,那就太好了。Trials对象允许我们这样做。我们只需要再导入几个项目

    from hyperopt import fmin, tpe, hp, STATUS_OK, Trials
    
    fspace = {
        'x': hp.uniform('x', -5, 5)
    }
    
    def f(params):
        x = params['x']
        val = x**2
        return {'loss': val, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(fn=f, space=fspace, algo=tpe.suggest, max_evals=50, trials=trials)
    
    print 'best:', best
    
    print 'trials:'
    for trial in trials.trials[:2]:
        print trial

    STATUS_OK 和 Trials是新导入的模块,Trials允许我们存储每一时间步长(time step)所存储的信息。然后我们可以输出这些函数在给定时间步长上对给定参数的求值。
    输出:

    best: {'x': 0.014420181637303776}
    trials:
    {'refresh_time': None, 'book_time': None, 'misc': {'tid': 0, 'idxs': {'x': [0]}, 'cmd': ('domain_attachment', 'FMinIter_Domain'), 'vals': {'x': [1.9646918559786162]}, 'workdir': None}, 'state': 2, 'tid': 0, 'exp_key': None, 'version': 0, 'result': {'status': 'ok', 'loss': 3.8600140889486996}, 'owner': None, 'spec': None}
    {'refresh_time': None, 'book_time': None, 'misc': {'tid': 1, 'idxs': {'x': [1]}, 'cmd': ('domain_attachment', 'FMinIter_Domain'), 'vals': {'x': [-3.9393509404526728]}, 'workdir': None}, 'state': 2, 'tid': 1, 'exp_key': None, 'version': 0, 'result': {'status': 'ok', 'loss': 15.518485832045357}, 'owner': None, 'spec': None}

    Trials对象将数据存储为BSON对象,类似于JSON对象一样。BSON来自pymongo模块,着这里我们不讨论细节,但是对于hyperopt有一些高级选项需要使用MongoDB进行分布式计算,因此导入pymongo。
    回到上面的输出,’tid’表示时间id,也就是时间步长,范围0到max_evals-1,每次迭代加1;’x’在’vals’键中,也就是每次迭代参数存储的地方;’loss’在’result’键中,是每次迭代目标函数的值。

    可视化(Visualization)

    这里介绍两种类型可视化,val vs. time和loss vs. val。
    首先val vs. time。下面是trials.trials数据描述可视化的代码和样本输出。

    f, ax = plt.subplots(1)
    xs = [t['tid'] for t in trials.trials]
    ys = [t['misc']['vals']['x'] for t in trials.trials]
    ax.set_xlim(xs[0]-10, xs[-1]+10)
    ax.scatter(xs, ys, s=20, linewidth=0.01, alpha=0.75)
    ax.set_title('$x$ $vs$ $t$ ', fontsize=18)
    ax.set_xlabel('$t$', fontsize=16)
    ax.set_ylabel('$x$', fontsize=16)

    输出如下(假设我们将max_evals设置为1000):
    val vs. time
    我们可以看到,最初算法从整个范围中均匀取值,但是随着时间的增加以及对于参数在目标函数上效果的学习,算法搜索范围越来越集中到最可能取得最优值的范围-0附近。它仍然探索整个解决方案空间,但不太频繁。

    loss vs. val的可视化:

    f, ax = plt.subplots(1)
    xs = [t['misc']['vals']['x'] for t in trials.trials]
    ys = [t['result']['loss'] for t in trials.trials]
    ax.scatter(xs, ys, s=20, linewidth=0.01, alpha=0.75)
    ax.set_title('$val$ $vs$ $x$ ', fontsize=18)
    ax.set_xlabel('$x$', fontsize=16)
    ax.set_ylabel('$val$', fontsize=16)

    loss vs. val
    这就是我们期望的,因为函数y(x) = x**2是确定性的。
    最后,让我们尝试一个更复杂的示例,使用更多的随机性和更多的参数。

    鸢尾花数据集(The Iris Dataset)

    在本节中,我们将介绍在经典数据集Iris上使用hyperopt进行参数调优的4个完整示例。我们将介绍k近邻(KNN)、支持向量机(SVM)、决策树和随机森林。注意,由于我们试图最大化交叉验证的准确性(下面代码中的acc),我们必须为hyperopt对这个值进行取负数,因为hyperopt只知道如何最小化函数。最小化函数f等于最大化函数f的复数。
    对于这项任务,我们将使用经典的Iris数据集,并进行一些有监督的机器学习。有4个输入特性和3个输出类。这些数据被标记为属于0类、1类或2类,它们映射到不同种类的鸢尾花。输入有4列:萼片长度(sepal length)、萼片宽度(sepal width)、花瓣长度(petal length)和花瓣宽度(pedal width)。输入单位是厘米。我们将使用这4个特性来学习预测三个输出类之一的模型。由于数据是由sklearn提供的,因此它有一个很好的DESCR属性,提供了关于数据集的详细信息。

    print iris.feature_names # input names
    print iris.target_names # output names
    print iris.DESCR # everything else

    让我们通过可视化特性和类来更好地了解数据,使用下面的代码。如果还没有安装seaborn,请不要忘记安装pip install seaborn。

    import seaborn as sns
    sns.set(style="whitegrid", palette="husl")
    
    iris = sns.load_dataset("iris")
    print iris.head()
    
    iris = pd.melt(iris, "species", var_name="measurement")
    print iris.head()
    
    f, ax = plt.subplots(1, figsize=(15,10))
    sns.stripplot(x="measurement", y="value", hue="species", data=iris, jitter=True, edgecolor="white", ax=ax)

    如图:
    iris

    K最近邻(K-Nearest Neighbors)

    我们现在使用hyperopt找到k近邻(KNN)机器学习模型的最佳参数。KNN模型根据训练数据集中k个最近的数据点的多数类,将测试集中的数据点进行分类。
    关于这个算法的更多信息可以在这里找到。下面的代码包含了我们已经讨论过的所有内容。

    from sklearn import datasets
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    
    def hyperopt_train_test(params):
        clf = KNeighborsClassifier(**params)
        return cross_val_score(clf, X, y).mean()
    
    space4knn = {
        'n_neighbors': hp.choice('n_neighbors', range(1,100))
    }
    
    def f(params):
        acc = hyperopt_train_test(params)
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space4knn, algo=tpe.suggest, max_evals=100, trials=trials)
    print 'best:'
    print best

    现在我们来看看输出图。y轴是交叉验证得分,x轴是k-最近邻中的k值。下面是代码及其图像:

    f, ax = plt.subplots(1)#, figsize=(10,10))
    xs = [t['misc']['vals']['n_neighbors'] for t in trials.trials]
    ys = [-t['result']['loss'] for t in trials.trials]
    ax.scatter(xs, ys, s=20, linewidth=0.01, alpha=0.5)
    ax.set_title('Iris Dataset - KNN', fontsize=18)
    ax.set_xlabel('n_neighbors', fontsize=12)
    ax.set_ylabel('cross validation accuracy', fontsize=12)

    knn
    当k大于63时,准确率急剧下降。这是由于数据集中每个类的数量。这三个类中的每个类只有50个实例。因此,让我们通过将’n_neighbors’的值限制为较小的值进行深入研究。

    from sklearn import datasets
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    
    def hyperopt_train_test(params):
        clf = KNeighborsClassifier(**params)
        return cross_val_score(clf, X, y).mean()
    
    space4knn = {
        'n_neighbors': hp.choice('n_neighbors', range(1,50))
    }
    
    def f(params):
        acc = hyperopt_train_test(params)
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space4knn, algo=tpe.suggest, max_evals=100, trials=trials)
    print 'best:'
    print best

    下面是当我们运行相同的可视化代码时得到的结果:
    knn-2
    现在我们可以清楚地看到k在k = 4处有一个最佳值。

    上面的模型不做任何预处理。让我们对我们的特性进行规范化和缩放看看这是否有帮助。使用这段代码:

    # now with scaling as an option
    from sklearn import datasets
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    
    def hyperopt_train_test(params):
        X_ = X[:]
    
        if 'normalize' in params:
            if params['normalize'] == 1:
                X_ = normalize(X_)
                del params['normalize']
    
        if 'scale' in params:
            if params['scale'] == 1:
                X_ = scale(X_)
                del params['scale']
    
        clf = KNeighborsClassifier(**params)
        return cross_val_score(clf, X_, y).mean()
    
    space4knn = {
        'n_neighbors': hp.choice('n_neighbors', range(1,50)),
        'scale': hp.choice('scale', [0, 1]),
        'normalize': hp.choice('normalize', [0, 1])
    }
    
    def f(params):
        acc = hyperopt_train_test(params)
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space4knn, algo=tpe.suggest, max_evals=100, trials=trials)
    print 'best:'
    print best

    像这样画出参数:

    parameters = ['n_neighbors', 'scale', 'normalize']
    cols = len(parameters)
    f, axes = plt.subplots(nrows=1, ncols=cols, figsize=(15,5))
    cmap = plt.cm.jet
    for i, val in enumerate(parameters):
        xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
        ys = [-t['result']['loss'] for t in trials.trials]
        xs, ys = zip(\*sorted(zip(xs, ys)))
        ys = np.array(ys)
        axes[i].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.75, c=cmap(float(i)/len(parameters)))
        axes[i].set_title(val)

    knn-3
    我们发现,数据的缩放和/或规范化并不能提高预测的准确性。k的最佳值为4,准确率为98.6%。

    这对于一个简单模型KNN的参数调优非常有用。让我们看看支持向量机(SVM)能做些什么。

    支持向量机 (SVM)

    由于这是一个分类任务,我们将使用sklearn的SVC类。这是代码:

    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    
    def hyperopt_train_test(params):
        X_ = X[:]
    
        if 'normalize' in params:
            if params['normalize'] == 1:
                X_ = normalize(X_)
                del params['normalize']
    
        if 'scale' in params:
            if params['scale'] == 1:
                X_ = scale(X_)
                del params['scale']
    
        clf = SVC(**params)
        return cross_val_score(clf, X_, y).mean()
    
    space4svm = {
        'C': hp.uniform('C', 0, 20),
        'kernel': hp.choice('kernel', ['linear', 'sigmoid', 'poly', 'rbf']),
        'gamma': hp.uniform('gamma', 0, 20),
        'scale': hp.choice('scale', [0, 1]),
        'normalize': hp.choice('normalize', [0, 1])
    }
    
    def f(params):
        acc = hyperopt_train_test(params)
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space4svm, algo=tpe.suggest, max_evals=100, trials=trials)
    print 'best:'
    print best
    
    parameters = ['C', 'kernel', 'gamma', 'scale', 'normalize']
    cols = len(parameters)
    f, axes = plt.subplots(nrows=1, ncols=cols, figsize=(20,5))
    cmap = plt.cm.jet
    for i, val in enumerate(parameters):
        xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
        ys = [-t['result']['loss'] for t in trials.trials]
        xs, ys = zip(\*sorted(zip(xs, ys)))
        axes[i].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.25, c=cmap(float(i)/len(parameters)))
        axes[i].set_title(val)
        axes[i].set_ylim([0.9, 1.0])

    下面是我们得到的:
    svm
    同样,缩放和规范化也没有帮助。核函数的首选为最佳(linear),最佳C值为1.4168540399911616,最佳伽玛值为15.04230279483486。该参数集的分类准确率达到99.3%。

    决策树(Decision Trees)

    我们将只尝试对决策树的几个参数进行优化。这是代码。

    iris = datasets.load_iris()
    X_original = iris.data
    y_original = iris.target
    
    def hyperopt_train_test(params):
        X_ = X[:]
        if 'normalize' in params:
            if params['normalize'] == 1:
                X_ = normalize(X_)
                del params['normalize']
    
        if 'scale' in params:
            if params['scale'] == 1:
                X_ = scale(X_)
                del params['scale']
        clf = DecisionTreeClassifier(**params)
        return cross_val_score(clf, X, y).mean()
    
    space4dt = {
        'max_depth': hp.choice('max_depth', range(1,20)),
        'max_features': hp.choice('max_features', range(1,5)),
        'criterion': hp.choice('criterion', ["gini", "entropy"]),
        'scale': hp.choice('scale', [0, 1]),
        'normalize': hp.choice('normalize', [0, 1])
    }
    
    def f(params):
    acc = hyperopt_train_test(params)
    return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space4dt, algo=tpe.suggest, max_evals=300, trials=trials)
    print 'best:'
    print best

    输出如下,准确率为97.3%:

    {'max_features': 1, 'normalize': 0, 'scale': 0, 'criterion': 0, 'max_depth': 17}

    如图我们可以看到,在不同的尺度值、标准化值和标准值下,性能几乎没有差别。

    parameters = ['max_depth', 'max_features', 'criterion', 'scale', 'normalize'] # decision tree
    cols = len(parameters)
    f, axes = plt.subplots(nrows=1, ncols=cols, figsize=(20,5))
    cmap = plt.cm.jet
    for i, val in enumerate(parameters):
        xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
        ys = [-t['result']['loss'] for t in trials.trials]
        xs, ys = zip(\*sorted(zip(xs, ys)))
        ys = np.array(ys)
        axes[i].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.5, c=cmap(float(i)/len(parameters)))
        axes[i].set_title(val)
        #axes[i].set_ylim([0.9,1.0])

    dt

    随机森林(Random Forests)

    让我们看看集成分类器Random Forest发生了什么,它只是一组针对不同大小的数据分区训练的决策树,每个分区对一个输出类进行投票,并选择多数派类作为预测。

    iris = datasets.load_iris()
    X_original = iris.data
    y_original = iris.target
    
    def hyperopt_train_test(params):
        X_ = X[:]
        if 'normalize' in params:
            if params['normalize'] == 1:
                X_ = normalize(X_)
                del params['normalize']
    
        if 'scale' in params:
            if params['scale'] == 1:
                X_ = scale(X_)
                del params['scale']
        clf = RandomForestClassifier(**params)
        return cross_val_score(clf, X, y).mean()
    
    space4rf = {
        'max_depth': hp.choice('max_depth', range(1,20)),
        'max_features': hp.choice('max_features', range(1,5)),
        'n_estimators': hp.choice('n_estimators', range(1,20)),
        'criterion': hp.choice('criterion', ["gini", "entropy"]),
        'scale': hp.choice('scale', [0, 1]),
        'normalize': hp.choice('normalize', [0, 1])
    }
    
    best = 0
    def f(params):
        global best
        acc = hyperopt_train_test(params)
        if acc > best:
        best = acc
        print 'new best:', best, params
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space4rf, algo=tpe.suggest, max_evals=300, trials=trials)
    print 'best:'
    print best

    同样,我们只得到97.3%的准确率,和决策树一样。

    下面是绘制参数的代码:

    parameters = ['n_estimators', 'max_depth', 'max_features', 'criterion', 'scale', 'normalize']
    f, axes = plt.subplots(nrows=2, ncols=3, figsize=(15,10))
    cmap = plt.cm.jet
    for i, val in enumerate(parameters):
        print i, val
        xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
        ys = [-t['result']['loss'] for t in trials.trials]
        xs, ys = zip(\*sorted(zip(xs, ys)))
        ys = np.array(ys)
        axes[i/3,i%3].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.5, c=cmap(float(i)/len(parameters)))
        axes[i/3,i%3].set_title(val)
        #axes[i/3,i%3].set_ylim([0.9,1.0])

    rf

    所有模型(All Together Now)

    虽然自动调优一个模型的参数(例如SVM或KNN)既有趣又有指导意义,但更有用的是一次调优所有的参数并得到一个总体上最好的模型。这使我们能够同时比较所有的参数和所有的模型,这给了我们最好的模型。这是代码。

    digits = datasets.load_digits()
    X = digits.data
    y = digits.target
    print X.shape, y.shape
    
    def hyperopt_train_test(params):
        t = params['type']
        del params['type']
        if t == 'naive_bayes':
            clf = BernoulliNB(**params)
        elif t == 'svm':
            clf = SVC(**params)
        elif t == 'dtree':
            clf = DecisionTreeClassifier(**params)
        elif t == 'knn':
            clf = KNeighborsClassifier(**params)
        else:
            return 0
        return cross_val_score(clf, X, y).mean()
    
    space = hp.choice('classifier_type', [
        {
            'type': 'naive_bayes',
            'alpha': hp.uniform('alpha', 0.0, 2.0)
        },
        {
            'type': 'svm',
            'C': hp.uniform('C', 0, 10.0),
            'kernel': hp.choice('kernel', ['linear', 'rbf']),
            'gamma': hp.uniform('gamma', 0, 20.0)
        },
        {
            'type': 'randomforest',
            'max_depth': hp.choice('max_depth', range(1,20)),
            'max_features': hp.choice('max_features', range(1,5)),
            'n_estimators': hp.choice('n_estimators', range(1,20)),
            'criterion': hp.choice('criterion', ["gini", "entropy"]),
            'scale': hp.choice('scale', [0, 1]),
            'normalize': hp.choice('normalize', [0, 1])
        },
        {
            'type': 'knn',
            'n_neighbors': hp.choice('knn_n_neighbors', range(1,50))
        }
    ])
    
    count = 0
    best = 0
    def f(params):
        global best, count
        count += 1
        acc = hyperopt_train_test(params.copy())
        if acc > best:
            print 'new best:', acc, 'using', params['type']
            best = acc
        if count % 50 == 0:
            print 'iters:', count, ', acc:', acc, 'using', params
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space, algo=tpe.suggest, max_evals=1500, trials=trials)
    print 'best:'
    print best

    这段代码需要一段时间才能运行,因为我们增加了计算次数:max_evals=1500。当发现新的最佳精度时,还会增加输出以更新。奇怪的是,为什么使用这种方法没有找到我们在上面找到的最佳模型:SVM的kernel=linear,C=1.416,和gamma=15.042。

    总结

    我们已经介绍了一些简单的例子,比如最小化确定性线性函数,以及一些复杂的例子,比如调整随机森林参数。hyperopt的文档在这里。另一个关于hyperopt的好博客是FastML的。hyperopt作者撰写的SciPy会议论文是Hyperopt: A Python Library for Optimizing the Hyperparameters of Machine Learning Algorithms,附带一个视频教程。对工程细节的一种更科学的处理方法是Making a Science of Model Search
    这篇文章中的技术可以应用于除机器学习之外的许多领域,例如在epsilon的epsilon-greedy multi-armed bandit调优参数,或传递给图形生成器的参数,以形成具有某些特性的合成网络。稍后我们将对此进行更多的讨论。

    展开全文
  • Mysql参数优化对于不同的网站,及在线量等,以及机器硬件的配置都关系,优化不可能一次性完成,需要不断的观察以及调试,才可能的得到最佳的效果 Mysql参数优化对于不同的网站,及在线量等,以及机器硬件的配置...

    码字不易,转载请附原链,搬砖繁忙回复不及时见谅,技术交流请加QQ群:909211071

    Mysql性能优化、Mysql参数优化、Mysql配置优化。Mysql参数优化对于不同的网站,及在线量等,以及机器硬件的配置都有关系,优化不可能一次性完成,需要不断的观察以及调试,才有可能的得到最佳的效果

    更多MySQL缓冲区配置优化参考:https://success.blog.csdn.net/article/details/97396807

    Mysql参数优化对于不同的网站,及在线量等,以及机器硬件的配置都有关系,优化不可能一次性完成,需要不断的观察以及调试,才有可能的得到最佳的效果

    为了测试我们创建一个test1的库创建一个tb1的表,然后导入2万行数据

    mysql> select count(*) from test1.tb1;
    +----------+
    | count(*) |
    +----------+
    | 20000 |
    +----------+
    1 row in set (0.15 sec)</span>

    在手动插入一条其他数据。

    mysql> insert into test1.tb1 values(20001,admin,12322112123332,1999-1-1,2019-9-1,ppppppppppp); 
    Query OK, 1 row affected (0.00 sec)

    在没有优化之前我们使用mysqlslap来进行压力测试

    \
    我们可以看到没有优化之前,它所用的时间为41.761秒,接下来开始我们的配置优化

    下面列出了对性能优化影响较大的主要变量,主要分为连接请求的变量和缓冲区的变量

    1) 连接请求的变量

    Max_connections

    Mysql的最大连接数,如果服务器的并发请求量比较大,可以调高这个值,当然这是要建立在机器能够支撑的情况下,因为如果连接数越来越多,mysql会为每个连接提供缓冲区,就会开销的越多的内存,所以需要适当的调整该值,不能随便去提高设值。

    Mysql>show variables like '%max_connections%';
    Mysql>show status like '%max_user_connections%';

    如果max_used_connections跟max_connections相同那么就是max_connections设置过低或者超过服务器的负载上限了,低于10%则设置过大

    1.首先查看mysql默认的最大连接数(默认为151)

    mysql> show variables like "max_connections%";
    +-----------------+-------+
    | Variable_name | Value |
    +-----------------+-------+
    | max_connections | 151 |
    +-----------------+-------+
    1 row in set (0.02 sec)

    修改/etc/my.cnf在[mysqld]下添加以下内容,设置最大连接数为1024,重启mysql服务验证

    Max_connections=1024

    查看修改后的最大连接数

    mysql> show variables like "max_connections%";
    +-----------------+-------+
    | Variable_name | Value |
    +-----------------+-------+
    | max_connections | 1024 |
    +-----------------+-------+
    1 row in set (0.00 sec)

    2)back_log

    mysql能暂存的连接数量,当主要mysql线程在一个很短时间内得到非常多的连接请求时候它就会起作用,如果mysql的连接数据达到max_connections时候,新来的请求将会被存在堆栈中,等待某一连接释放资源,该推栈的数量及back_log,如果等待连接的数量超过back_log,将不被授予连接资源

    back_log值指出在mysql暂时停止回答新请求之前的短时间内有多少个请求可以被存在推栈中,只有如果期望在一个短时间内有很多连接的时候需要增加它

    当我们在观察主机进程列表

    mysql>show full processlist

    发现大量的待连接进程时,就需要加大back_log或者加大max_connections的值

    可以通过以下命令查看back_log的设置

    >mysql> show variables like '%back_log%';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | back_log | 254 |
    +---------------+-------+
    1 row in set (0.00 sec)

    修改/etc/my.cnf文件在[mysqld]下添加如下内容,设置最大连接数为1024,随后重启mysql服务再次查看

    mysql> show variables like '%back_log%';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | back_log | 1024 |
    +---------------+-------+
    1 row in set (0.00 sec)

    3)wait_timeout和interactive_timeout

    wait_timeout:指的是mysql在关闭一个非交互的连接之前所要等待的秒数
    interactive_timeoutz:指的是mysql在关闭一个交互的连接之前所需要等待的秒数,比如我们在终端上进行mysql管理,使用的即使交互的连接,这时候,如果没有操作的时间超过了interactive_time设置的时间就会自动的断开,默认的是28800,可调优为7200。wait_timeout:如果设置太小,那么连接关闭的就很快,从而使一些持久的连接不起作用
    如果设置太大,容易造成连接打开时间过长,在show processlist时候,能看到很多的连接 一般希望wait_timeout尽可能低

    查看wait_timeout和interactive_timeout的设置

    mysql> show variables like "%wait_timeout%";
    mysql> show variables like "%interactive_timeout%";

    \

    修改/etc/my.cnf,添加以下内容

    wait_timeout=100
    interactive_timeout=100

    重启mysql服务,再次查看

    \

    4)key_buffer_size
    key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度,通过key_read_requests和key_reads可以直到key_baffer_size设置是否合理。
    可以通过show status like "key_read%"查看

    mysql> show variables like "key_buffer_size%";
    +-----------------+---------+
    | Variable_name | Value |
    +-----------------+---------+
    | key_buffer_size | 8388608 |
    +-----------------+---------+
    1 row in set (0.00 sec)
    mysql> show status like "key_read%";
    +-------------------+-------+
    | Variable_name | Value |
    +-------------------+-------+
    | Key_read_requests | 6 |
    | Key_reads | 3 |
    +-------------------+-------+
    2 rows in set (0.01 sec)

    一共有6个索引读取请求,有三个请求在内存中没有找到直接从硬盘中读取索引

    key_buffer_size只对myisam表起作用,即使不使用myisam表,但是内部的临时磁盘表是myisam表,也要使用该值。可以使用检查状态值created_tmp_disk_tables得知

    mysql> show status like "created_tmp%";
    +-------------------------+-------+
    | Variable_name | Value |
    +-------------------------+-------+
    | Created_tmp_disk_tables | 0 |
    | Created_tmp_files | 5 |
    | Created_tmp_tables | 0 |
    +-------------------------+-------+
    3 rows in set (0.00 sec)

    默认配置数值是8388608我主机有2个G内存那么可调优为134217728(128MB)
    可以修改主配置文件添加如下内容

    key_buffer_size=128M

    重启mysql服务后再次查看

    5)query_cache_size(查询缓存简称QC)
    使用查询缓冲,mysql将查询结果存放在缓冲区中,今后对于同样的select语句(区分大小写),将直接从缓冲区中读取结果。
    一个sql查询如果以select开头,那么mysql服务器将尝试对其使用查询缓存。
    注:两个sql语句,只要想差哪怕是一个字符(列如大小写不一样;多一个空格等),那么这两个sql将使用不同的一个cache。
    上述状态值可以使用show status like &#39;Qcache%获得&#39;

    mysql> show status like "%Qcache%";
    +-------------------------+---------+
    | Variable_name | Value |
    +-------------------------+---------+
    | Qcache_free_blocks | 1 |
    | Qcache_free_memory | 1031832 |
    | Qcache_hits | 0 |
    | Qcache_inserts | 0 |
    | Qcache_lowmem_prunes | 0 |
    | Qcache_not_cached | 0 |
    | Qcache_queries_in_cache | 0 |
    | Qcache_total_blocks | 1 |
    +-------------------------+---------+
    8 rows in set (0.00 sec)

    Qcache_free_blocks:缓存中相邻内存块的个数。如果该值显示较大,则说明Query Cache 中的内存碎片较多了,FLUSH QUERY CACHE会对缓存中的碎片进行整理,从而得到一个空闲块。
    注:当一个表被更新之后,和它相关的cache blocks将被free。但是这个block依然可能存在队列中,除非是在队列的尾部。可以用FLUSH QUERY CACHE语句来清空free blocks
    Qcache_free_memory:Query Cache 中目前剩余的内存大小。通过这个参数我们可以较为准确的观察出当前系统中的Query Cache 内存大小是否足够,是需要增加还是过多了。
    Qcache_hits:表示有多少次命中缓存。我们主要可以通过该值来验证我们的查询缓存的效果。数字越大,缓存效果越理想。
    Qcache_inserts:表示多少次未命中然后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,执行查询处理后把结果insert到查询缓存中。这样的情况的次数越多,表示查询缓存应用到的比较少,效果也就不理想。当然系统刚启动后,查询缓存是空的,这很正常。
    Qcache_lowmem_prunes:多少条Query 因为内存不足而被清除出Query Cache。通过“Qcache_lowmem_prunes”和“Qcache_free_memory”相互结合,能够更清楚的了解到我们系统中Query Cache 的内存大小是否真的足够,是否非常频繁的出现因为内存不足而有Query 被换出。这个数字最好长时间来看;如果这个数字在不断增长,就表示可能碎片非常严重,或者内存很少。(上面的free_blocks和free_memory可以告诉您属于哪种情况)
    Qcache_not_cached:不适合进行缓存的查询的数量,通常是由于这些查询不是 SELECT 语句或者用了now()之类的函数。
    Qcache_queries_in_cache:当前Query Cache 中cache 的Query 数量;
    Qcache_total_blocks:当前Query Cache 中的block 数量;。
    我们再查询一下服务器关于query_cache的配置:


    \

    上图可以看出query_cache_type为off表示不缓存任何查询

    各字段的解释:
    query_cache_limit:超过此大小的查询将不缓存
    query_cache_min_res_unit:缓存块的最小大小 ,query_cache_min_res_unit的配置是一柄”双刃剑”,默认是4KB,设置值大对大数据查询有好处,但如果你的查询都是小数据查询,就容易造成内存碎片和浪费。
    query_cache_size:查询缓存大小 (注:QC存储的最小单位是1024 byte,所以如果你设定了一个不是1024的倍数的值,这个值会被四舍五入到最接近当前值的等于1024的倍数的值。)

    query_cache_type:缓存类型,决定缓存什么样的查询,注意这个值不能随便设置,必须设置为数字,可选项目以及说明如下:

    如果设置为0,那么可以说,你的缓存根本就没有用,相当于禁用了。

    如果设置为1,将会缓存所有的结果,除非你的select语句使用SQL_NO_CACHE禁用了查询缓存。

    如果设置为2,则只缓存在select语句中通过SQL_CACHE指定需要缓存的查询。

    修改/etc/my.cnf,配置完后的部分文件如下:

    query_cache_size=256M

    query_cache_type=1

    保存文件,重新启动MYSQL服务,然后通过如下查询来验证是否真正开启了:

    \

    6)max_connect_errors是一个mysql中与安全有关的计数器值,它负责阻止过多尝试失败的客户端以防止暴力破解密码等情况,当超过指定次数,mysql服务器将禁止host的连接请求,直到mysql服务器重启或通过flush hosts命令清空此host的相关信息 max_connect_errors的值与性能并无太大关系。
    修改/etc/my.cnf文件,在[mysqld]下面添加如下内容
    max_connect_errors=20

    修改完后重启mysql服务

    7)sort_buffer_size
    每个需要进行排序的线程分配该大小的一个缓冲区。增加这值加速ORDER BY 或GROUP BY操作,Sort_Buffer_Size并不是越大越好,由于是connection级的参数,过大的设置+高并发可能会耗尽系统内存资源。列如:500个连接将会消耗500*sort_buffer_size(2M)=1G内存
    修改/etc/my.cnf文件,在[mysqld]下面添加如下:

    sort_buffer_size=2M

    8)max_allowed_packet=32M
    mysql根据配置文件会限制,server接受的数据包大小。有时候大的插入和更新会受max_allowed_packet参数限制,导致写入或者更新失败,更大值是1GB,必须设置1024的倍数

    9)join_buffer_size=2M
    用于表间关联缓存的大小,和sort_buffer_size一样,该参数对应的分配内存也是每个连接独享。

    10)thread_cache_size = 300
    服务器线程缓存,这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时,那么客户端的线程将被放到缓存中以响应下一个客户而不是销毁(前提是缓存数未达上限),如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能.通过比较 Connections 和 Threads_created 状态的变量,可以看到这个变量的作用。设置规则如下:1GB 内存配置为8,2GB配置为16,3GB配置为32,4GB或更高内存,可配置更大。服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)

    \

    试图连接到MySQL(不管是否连接成功)的连接数

    >mysql> show status like '%threads_%';
    +-------------------+-------+
    | Variable_name | Value |
    +-------------------+-------+
    | Threads_cached | 0 |
    | Threads_connected | 1 |
    | Threads_created | 1 |
    | Threads_running | 1 |
    +-------------------+-------+
    4 rows in set (0.00 sec)

    Threads_cached :代表当前此时此刻线程缓存中有多少空闲线程。
    Threads_connected :代表当前已建立连接的数量,因为一个连接就需要一个线程,所以也可以看成当前被使用的线程数。
    Threads_created :代表从最近一次服务启动,已创建线程的数量,如果发现Threads_created值过大的话,表明MySQL服务器一直在创建线程,这也是比较耗资源,可以适当增加配置文件中thread_cache_size值。
    Threads_running :代表当前激活的(非睡眠状态)线程数。并不是代表正在使用的线程数,有时候连接已建立,但是连接处于sleep状态。

    11.innodb_buffer_pool_size

    对于InnoDB表来说,innodb_buffer_pool_size的作用就相当于key_buffer_size对于MyISAM表的作用一样。InnoDB使用该参数指定大小的内存来缓冲数据和索引。对于单独的MySQL数据库服务器,最大可以把该值设置成物理内存的80%。

    mysql> show variables like '%innodb_buffer_pool_size%';

    设置innodb_buffer_pool_size

    修改/etc/my.cnf文件,在[mysqld]下面添加如下内容

    innodb_buffer_pool_size = 2048M

    重启MySQL Server进入后,查看设置已经生效。

    12. innodb_flush_log_at_trx_commit

    主要控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为0、1、2三个。0,表示当事务提交时,不做日志写入操作,而是每秒钟将log buffer中的数据写入日志文件并flush磁盘一次;1,则在每秒钟或是每次事物的提交都会引起日志文件写入、flush磁盘的操作,确保了事务的ACID;设置为2,每次事务提交引起写入日志文件的动作,但每秒钟完成一次flush磁盘操作。

    实际测试发现,该值对插入数据的速度影响非常大,设置为2时插入10000条记录只需要2秒,设置为0时只需要1秒,而设置为1时则需要229秒。因此,MySQL手册也建议尽量将插入操作合并成一个事务,这样可以大幅提高速度。

    根据MySQL手册,在允许丢失最近部分事务的危险的前提下,可以把该值设为0或2。

    13.innodb_thread_concurrency = 0
    此参数用来设置innodb线程的并发数量,默认值为0表示不限制,若要设置则与服务器的CPU核数相同或是cpu的核数的2倍,建议用默认设置,一般为8.

    14.innodb_log_buffer_size

    此参数确定些日志文件所用的内存大小,以M为单位。缓冲区更大能提高性能,对于较大的事务,可以增大缓存大小。

    innodb_log_buffer_size=32M

    15. innodb_log_file_size = 50M

    此参数确定数据日志文件的大小,以M为单位,更大的设置可以提高性能.

    16. innodb_log_files_in_group = 3

    为提高性能,MySQL可以以循环方式将日志文件写到多个文件。推荐设置为3

    17.read_buffer_size = 1M
    MySql 读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql会为它分配一段内存缓冲区。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能。和 sort_buffer_size一样,该参数对应的分配内存也是每个连接独享

    18.read_rnd_buffer_size = 16M
    MySql 的随机读(查询操作)缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySql会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
    注:顺序读是指根据索引的叶节点数据就能顺序地读取所需要的行数据。随机读是指一般需要根据辅助索引叶节点中的主键寻找实际行数据,而辅助索引和主键所在的数据段不同,因此访问方式是随机的。

    19.bulk_insert_buffer_size = 64M
    批量插入数据缓存大小,可以有效提高插入效率,默认为8M

    20.binary log

    log-bin=/usr/local/mysql/data/mysql-bin

    binlog_cache_size = 2M //为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存, 提高记录bin-log的效率。没有什么大事务,dml也不是很频繁的情况下可以设置小一点,如果事务大而且多,dml操作也频繁,则可以适当的调大一点。前者建议是--1M,后者建议是:即 2--4M

    max_binlog_cache_size = 8M //表示的是binlog 能够使用的最大cache 内存大小

    max_binlog_size= 512M //指定binlog日志文件的大小,如果当前的日志大小达到max_binlog_size,还会自动创建新的二进制日志。你不能将该变量设置为大于1GB或小于4096字节。默认值是1GB。在导入大容量的sql文件时,建议关闭sql_log_bin,否则硬盘扛不住,而且建议定期做删除。

    expire_logs_days = 7 //定义了mysql清除过期日志的时间。

    二进制日志自动删除的天数。默认值为0,表示“没有自动删除”。

    mysqladmin flush-logs 也可以重新开始新的binarylog

    相关优化参数总结:

    slow_query_log=1
    slow_query_log_file = /usr/local/mysql/data/slow_query_log
    long_query_time=1
    log-queries-not-using-indexes
    max_connections=1024
    back_log=128
    wait_timeout=60
    interactive_timeout=7200
    key_buffer_size=256M
    query_cache_size=256M
    query_cache_type=1
    query_cache_limit=50M
    max_connect_errors=20
    sort_buffer_size=2M
    max_allowed_packet=32M
    join_buffer_size=2M
    thread_cache_size=200
    innodb_buffer_pool_size=2048M
    innodb_flush_log_at_trx_commit=1
    innodb_log_buffer_size=32M
    innodb_log_file_size=128M
    innodb_log_files_in_group=3
    log-bin=mysql-bin
    binlog_cache_size=2M
    max_binlog_cache_size=8M
    max_binlog_size=512M
    expire_logs_days=7
    read_buffer_size=1M
    read_rnd_buffer_size=16M
    bulk_insert_buffer_size=64M
    server-id=1

    优化结束后,再次进行压力测试,查看效果

    \

     

     

     

    展开全文
  • 本文受 浅析 Hinton 最近提出的 Capsule 计划 启发,希望以更通俗的方式推广机器学习算法,让数学基础和编程能力的人能够乐享其中。 目前人工智能和深度学习越趋普及,大家可以使用开源的Scikit-learn、...

    简介

    本文受 浅析 Hinton 最近提出的 Capsule 计划 启发,希望以更通俗的方式推广机器学习算法,让有数学基础和编程能力的人能够乐享其中。

    目前人工智能和深度学习越趋普及,大家可以使用开源的Scikit-learn、TensorFlow来实现机器学习模型,甚至参加Kaggle这样的建模比赛。那么要想模型效果好,手动调参少不了,机器学习算法如SVM就有gamma、kernel、ceof等超参数要调,而神经网络模型有learning_rate、optimizer、L1/L2 normalization等更多超参数可以调优。

    很多paper使用一个新的模型可以取得state of the art的效果,然后提供一组超参数组合方便读者复现效果,实际上这些超参数都是“精挑细选”得到的,背后有太多效果不好的超参数尝试过程被忽略,大家也不知道对方的超参数是如何tune出来的。因此,了解和掌握更好的超参数调优方法在科研和工程上是很有价值的,本文将介绍一种更好的超参数调优方式,也就是贝叶斯优化(Bayesian Optimization),以及开源调参服务Advisor的使用介绍。

    超参数介绍

    首先,什么是超参数(Hyper-parameter)?这是相对于模型的参数而言(Parameter),我们知道机器学习其实就是机器通过某种算法学习数据的计算过程,通过学习得到的模型本质上是一些列数字,如树模型每个节点上判断属于左右子树的一个数,或者逻辑回归模型里的一维数组,这些都称为模型的参数。

    那么定义模型属性或者定义训练过程的参数,我们称为超参数,例如我们定义一个神经网络模型有9527层网络并且都用RELU作为激活函数,这个9527层和RELU激活函数就是一组超参数,又例如我们定义这个模型使用RMSProp优化算法和learning rate为0.01,那么这两个控制训练过程的属性也是超参数。

    显然,超参数的选择对模型最终的效果有极大的影响。如复杂的模型可能有更好的表达能力来处理不同类别的数据,但也可能因为层数太多导致梯度消失无法训练,又如learning rate过大可能导致收敛效果差,过小又可能收敛速度过慢。

    那么如何选择合适的超参数呢,不同模型会有不同的最优超参数组合,找到这组最优超参数大家会根据经验、或者随机的方法来尝试,这也是为什么现在的深度学习工程师也被戏称为“调参工程师”。根据No Free Lunch原理,不存在一组完美的超参数适合所有模型,那么调参看起来是一个工程问题,有可能用数学或者机器学习模型来解决模型本身超参数的选择问题吗?答案显然是有的,而且通过一些数学证明,我们使用算法“很有可能”取得比常用方法更好的效果,为什么是“很有可能”,因为这里没有绝对只有概率分布,也就是后面会介绍到的贝叶斯优化。

    自动调参算法

    说到自动调参算法,大家可能已经知道了Grid search(网格搜索)、Random search(随机搜索),还有Genetic algorithm(遗传算法)、Paticle Swarm Optimization(粒子群优化)、Bayesian Optimization(贝叶斯优化)、TPE、SMAC等。

    这里补充一个背景,机器学习模型超参数调优一般认为是一个黑盒优化问题,所谓黑盒问题就是我们在调优的过程中只看到模型的输入和输出,不能获取模型训练过程的梯度信息,也不能假设模型超参数和最终指标符合凸优化条件,否则的话我们通过求导或者凸优化方法就可以求导最优解,不需要使用这些黑盒优化算法,而实际上大部分的模型超参数也符合这个场景。其次是模型的训练过程是相对expensive的,不能通过快速计算获取大量样本,我们知道DeepMind用增强学习模型DQN来打Atari游戏,实际上每一个action操作后都能迅速取得当前的score,这样收集到大量样本才可以训练复杂的神经网络模型,虽说我们也可以用增强学习来训练超参数调优的模型,但实际上一组超参数要训练一个模型需要几分钟、几小时、几天甚至几个月的时间,无法快速获取这么多样本数据,因此需要有更“准确和高效”的方法来调优超参数。

    像遗传算法和PSO这些经典黑盒优化算法,我归类为群体优化算法,也不是特别适合模型超参数调优场景,因为需要有足够多的初始样本点,并且优化效率不是特别高,本文也不再详细叙述。

    目前业界用得比较多的分别是Grid search、Random search和Bayesian Optimization。网格搜索很容易理解和实现,例如我们的超参数A有2种选择,超参数B有3种选择,超参数C有5种选择,那么我们所有的超参数组合就有2 * 3 * 5也就是30种,我们需要遍历这30种组合并且找到其中最优的方案,对于连续值我们还需要等间距采样。实际上这30种组合不一定取得全局最优解,而且计算量很大很容易组合爆炸,并不是一种高效的参数调优方法。

    业界公认的Random search效果会比Grid search好,Random search其实就是随机搜索,例如前面的场景A有2种选择、B有3种、C有5种、连续值随机采样,那么每次分别在A、B、C中随机取值组合成新的超参数组合来训练。虽然有随机因素,但随机搜索可能出现效果特别差、也可能出现效果特别好,在尝试次数和Grid search相同的情况下一般最值会更大,当然variance也更大但这不影响最终结果。在实现Random search时可以优化,过滤随机可能出现过的超参数组合,不需要重复计算。

    实际上Grid search和Random search都是非常普通和效果一般的方法,在计算资源有限的情况下不一定比建模工程师的个人经验要好,接下来介绍的Bayesian Optimization就是“很可能”比普通开发者或者建模工程师调参能力更好的算法。首先贝叶斯优化当然用到了贝叶斯公式,这里不作详细证明了,它要求已经存在几个样本点(同样存在冷启动问题,后面介绍解决方案),并且通过高斯过程回归(假设超参数间符合联合高斯分布)计算前面n个点的后验概率分布,得到每一个超参数在每一个取值点的期望均值和方差,其中均值代表这个点最终的期望效果,均值越大表示模型最终指标越大,方差表示这个点的效果不确定性,方差越大表示这个点不确定是否可能取得最大值非常值得去探索。因此实现贝叶斯优化第一步就是实现高斯过程回归算法,并且这里可以通过类似SVM的kernel trick来优化计算,在后面的开源项目Advisor介绍中我们就使用Scikit-learn提供的GaussianProgressRegressor,最终效果如下图,在只有3个初始样本的情况下我们(通过100000个点的采样)计算出每个点的均值和方差。

    从曲线可以看出,中间的点均值较大,而且方差也比较大,很有可能这个点的超参数可以训练得到一个效果指标好的模型。那为什么要选均值大和方差大的点呢?因为前面提到均值代表期望的最终结果,当然是越大越好,但我们不能每次都挑选均值最大的,因为有的点方差很大也有可能存在全局最优解,因此选择均值大的点我们成为exploritation(开发),选择方差大的点我们称为exploration(探索)。那么究竟什么时候开发什么时候探索,并且开发和探索各占多少比例呢?不同的场景其实是可以有不同的策略的,例如我们的模型训练非常慢,只能再跑1组超参数了,那应该选择均值较大的比较有把握,如果我们计算力还能可以跑1000次,那么就不能放弃探索的机会应该选择方差大的,而至于均值和方差比例如何把握,这就是我们要定义的acquisition function了。acquisition function是一个权衡exploritation和exploration的函数,最简单的acquisition function就是均值加上n倍方差(Upper condence bound算法),这个n可以是整数、小数或者是正数、负数,更复杂的acquisition function还有Expected improvement、Entropy search等等。在原来的图上加上acquisition function曲线,然后我们求得acquisition function的最大值,这是的参数值就是贝叶斯优化算法推荐的超参数值,是根据超参数间的联合概率分布求出来、并且均衡了开发和探索后得到的结果。

    因此如果我们使用贝叶斯优化,那么我们下一个点就取中间偏左的点,使用这个点代表的超参数来训练模型,并且得到这个模型在这住超参数组合下的效果指标。有了新的指标,贝叶斯优化模型的样本就从3个变成了4个,这样可以重新计算超参数之间的后验概率分布和acquisition function,效果如下图。

    从均值和方差曲线看出,目前右边的点均值不低,并且方差是比较大,直观上我们认为探索右边区域的超参数是“很可能”有价值的。从acquisition function曲线我们也可以看出,右边的点在考虑了开发和探索的情况下有更高的值,因此我们下一个超参数推荐就是右边星号的点。然后我们使用推荐的超参数继续训练,得到新的模型效果指标,加入到高斯过程回归模型里面,得到新的均值-方差曲线和acquisition function曲线。

    通过不断重复上述的步骤,我们的曲线在样本极少的情况下也可以毕竟最终真实的曲线。当然上面的图是在一个黑盒优化问题上模拟的,因此我们知道真实的曲线形状,现实的机器学习模型的超参数间不一定能画出完整的曲线,但通过符合联合高斯概率分布的假设,还有高斯过程回归、贝叶斯方程等数学证明,我们可以从概率上找到一个“很可能”更好的超参数,这是比Grid search或者Random search更有价值的方法。

    注意,前面提到的Bayesian Optimization等超参数优化算法也是有超参数的,或者称为超超参数,如acquisition function的选择就是可能影响超参数调优模型的效果,但一般而言这些算法的超超参数极少甚至无须调参,大家选择业界公认效果比较好的方案即可。

    Google Vizier

    前面已经介绍了Grid search、Random search和Bayesian Optimization等算法,但并不没有完,因为我们要使用这些自动调参算法不可能都重新实现一遍,我们应该关注于自身的机器学习模型实现而直接使用开源或者易用的调参服务。

    近期Google就开放了内部调参系统Google Vizier的论文介绍,感兴趣可以在这里阅读paper https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46180.pdf

    与开源的hyperopt、optunity不同,Vizier是一个service而不是一个library,也就是算法开发者不需要自己部署调参服务或者管理参数存储,只需要选择合适的调参算法,如贝叶斯优化,然后Vizier就会根据模型的一些历史指标推荐最优的超参数组合给开发者,直接使用这些超参数会比自己瞎猜或者遍历参数组合得到的效果更好。当然开发者可以使用Vizier提供的Algorithm Playground功能实现自己的自动调参算法,还有内置一些EarlyStopAlgorithm也可以提前发现一些“没有前途”的调优任务提前结束剩下计算资源。

    目前Google Vizier已经支持Grid search、Random search已经改良过的Bayesian optimization,为什么是改良过的呢?前面提到贝叶斯优化也需要几个初始样本点,这些样本点一般通过随机搜索要产生,这就有冷启动的代价了,Google将不同模型的参数都归一化进行统一编码,每个任务计算的GaussianProcessRegressor与上一个任务的GaussianProcessRegressor计算的残差作为目标来训练,对应的acquisition function也不是简单的均值乘以n倍方差了,这相当于用了迁移学习模型的概念,从paper的效果看基本解决了冷启动的问题,这个模型被称为(Stacked)Batch Gaussian Process Bandit。

    Google Vizier除了实现很好的参数推荐算法,还定义了Study、Trial、Algorithm等非常好的领域抽象,这套系统也直接应用到Google CloudML的HyperTune subsystem中,开发者只需要写一个JSON配置文件就可以在Google Cloud上自动并行多任务调参了。

    Advisor开源项目

    Google Vizier是目前我看过最赞的超参数自动调优服务,可惜的是它并没有开源,外部也只有通过Google CloudML提交的任务可以使用其接口,不过其合理的基础架构让我们也可以重现一个类似的自动调参服务。

    Advisor就是一个Google Vizier的开源实现,不仅实现了和Vizier完全一致的Study、Trial、Algorithm领域抽象,还提供Grid search、Random search和Bayesian optimization等算法实现。使用Advisor很简单,我们提供了API、SDK、Web以及命令行等多种访问方式,并且已经集成Scikit-learn、XGBoost和TensorFlow等开源机器学习框架,基本只要写一个Python函数定义好模型输入和指标就可以实现任意的超参数调优(黑盒优化)功能。

    Advisor使用Python实现,基于Scikit-learn的GPR实现了贝叶斯优化等算法,也欢迎更多开发者参与,开源地址 tobegit3hub/advisor 。

    Advisor在线服务

    hypertune.cn 是我们提供的在线超参数推荐服务,也是体验Advisor调参服务的最好入口,在网页上我们就可以使用所有的Grid search、Random search、Bayesian optimization等算法功能了。

    首先打开 http://hypertune.cn , 目前我们已经支持使用Github账号登录,由于还没有多租户权限隔离因此不需要登录也可以访问全局信息。在首页我们可以查看所有的Study,也就是每一个模型训练任务的信息,也可以在浏览器上直接创建Study。

    这里需要用户定义Study configuration,也就是模型超参数的search space,和Google Vizier一样我们支持Double、Integer、Discrete和Categorical四种类型的超参数定义,基本涵盖了数值型、字符串、连续型以及离散型的任意超参数类别,更详细的例子如下图。

    定义好Study好,我们可以进入Study详情页,直接点击“Generate Suggestions”按钮生成推荐的超参数组合,这会根据用户创建Study选择的调参算法(如BayesianOptimization)来推荐,底层就是基于Scikit-learn实现的联合高斯分布、高斯过程回归、核技巧、贝叶斯优化等算法实现。

    当然我们也可以使用Grid search、Random search等朴素的搜索算法,生成的Trial就是使用的该超参数组合的一次运行,默认是没有objective value的,我们可以在外部使用该超参数进行模型训练,然后把auc、accuracy、mean square error等指标在网页上回填到参数推荐服务,下一次超参数推荐就会基于已经训练得到模型数据,进行更优化、权衡exploritation和exploration后的算法推荐。对于Eearly stop算法,我们还需要每一步的性能指标,因此用户可以提供Training step以及对应的Objective value,进行更细化的优化。

    除了提供在网页上集成推荐算法,我们也集成了Scikit-learn、XGBoost和TensorFlow等框架,在命令行只要定义一个函数就可以自动实现创建Study、获取Trial以及更新Trial metrics等功能,参考 https://github.com/tobegit3hub/advisor/tree/master/examples 。对于贝叶斯优化算法,我们还提供了一维特征的可视化工具,像上面的图一样直观地感受均值、方差、acquisition function的变化,参考 https://github.com/tobegit3hub/advisor/tree/master/visualization 。

    总结

    本文介绍了一种更好的超参数调优方法,也就是贝叶斯优化算法,并且介绍了Google内部的Vizier调参服务以及其开源实现Advisor项目。通过使用更好的模型和工具,可以辅助机器学习工程师的建模流程,在学术界和工业界取得更多、更大的突破。

    如果你有更好的超参数推荐算法,不妨留言,我们有能力实现并且让更多人用上 :)

    展开全文
  • Redis集群配置参数优化

    万次阅读 2018-01-12 15:39:28
    Redis的主要参数配置在redis.conf文件中。 1. conf 内存值 2.bind ip 默认情况下,如果没有指定“bind”配置指令,Redis将侦听服务器上可用的所有网络接口的连接。 默认情况:bind 127.0.0.1 实际配置:bind 本机ip ...
  • 公众号标题:神经网络中的优化方法之学习率衰减和动态梯度方向 引言 神经网络中的网络优化和正则化问题介绍主要分为一,二...无论是神经网络还是机器学习都会存在很多的超参数,在神经网络中,常见的超参数有: 网...
  • 1、 Mapper/Reducer阶段JVM内存溢出(一般都是堆) 1) JVM堆(Heap)内存溢出:堆内存不足时,一般会抛出如下异常: 第一:“java.lang.OutOfMemoryError:” GC overhead limit exceeded; 第二:“Error: Java...
  • 【Unity】中GC优化XLua下的各种值类型

    千次阅读 2017-02-17 15:35:21
    Unity下的C#GC Alloc(下面简称gc)是个大问题,而嵌入一个动态类型的Lua后,它们之间的交互很容易就产生gc,各种Lua方案也把这作为性能优化的重点。这些优化说穿了其实不复杂。 元凶在这里 先看看这个函数 ...
  • 史上最强Tomcat8性能优化

    万次阅读 多人点赞 2019-10-25 15:33:32
    文章目录授人以鱼不如授人以渔目的服务器资源Tomcat配置优化Linux环境安装运行Tomcat8AJP连接执行器(线程池)3运行模式部署测试用的web项目查看服务器信息部署web应用使用Apache JMeter进行性能测试下载安装修改...
  • SSL优化
  • scipy数值优化参数估计

    万次阅读 2017-04-11 10:07:38
    引言优化是一门大学问,这里不讲数学原理,我假设你还记得一点高数的知识,并且看得懂python代码。关于求解方程的参数,这个在数据挖掘或问题研究中经常碰到,比如下面的回归方程式,是挖掘算法中最简单最常用的了,...
  • Tomcat 调优及 JVM 参数优化

    万次阅读 多人点赞 2016-06-22 16:20:14
    Tomcat 的缺省配置是不能稳定长期运行的,也就是不适合生产环境,它会死机,让你不断重新启动,甚至在午夜时分唤醒你。...Tomcat 的优化不像其它软件那样,简简单单的修改几个参数就可以了,它的优化主要
  • Mencoder的常用h264优化参数和建议

    千次阅读 2011-12-09 15:08:41
    转载本站文章请注明,转载自:扶凯[http://www.php-oa.com] ... x264在着非常好的压缩比,在同等码流上比别的视频清楚多了,如下是最常常用参数优化.使用的2次pass 1st pass mencoder -sws 9 -oac faac -faacopts
  • 神经网络的参数优化方法

    万次阅读 多人点赞 2018-10-23 14:05:42
    著名: 本文是从 Michael Nielsen的电子书Neural Network and Deep Learning的深度学习那一章的卷积神经网络的参数优化方法的一些总结和摘录,并不是我自己的结论和做实验所得到的结果。我想Michael的实验结果更...
  • 写的很好,推荐阅读。 ... ...在日常的运维工作中,经常会用到...今天这里简单梳理下nginx性能优化的配置(仅仅依据本人的实战经验而述,如不妥,敬请指出~) 一、这里的优化主要是指对nginx的配置优化,一般来说n
  • 参数优---贝叶斯优化及其改进(PBT优化

    千次阅读 多人点赞 2020-01-08 21:14:34
    自动机器学习超参数调整(贝叶斯优化)—介绍了例子 贝叶斯优化(Bayesian Optimization)深入理解 贝叶斯优化(BayesianOptimization) 简介 所谓优化,实际上就是一个求极值的过程,数据科学的很多时候就是求极值...
  • 变长模板、变长参数是依靠C++...了这个强大的工具,我们可以编写更加丰富的函数,例如任意类型参数的printf等。由于这个技术还比较新,还没有见到成熟的用法用例,我把我尝试的一些结果总结如下,希望对大家帮助。
  • MySQL数据库优化的八方式(经典必看)

    万次阅读 多人点赞 2019-03-13 15:48:28
    MySQL数据库优化的八方式(经典必看) 引言: 关于数据库优化,网上不少资料和方法,但是不少质量参差不齐,有些总结的不够到位,内容冗杂 偶尔发现了这篇文章,总结得很经典,文章流量也很大,所以拿...
  • MySQL性能优化参数配置

    万次阅读 2013-12-18 13:34:25
    通过根据服务器目前状况,修改Mysql的系统参数,达到合理利用服务器现有资源,最大合理的提高MySQL性能。   2、服务器参数: 32G内存、4个CPU,每个CPU 8核。 3、MySQL目前安装状况。  MySQL目前...
  • 如何配置我们的JVM呢,首先我们需要知道JVM的参数有哪些,然后根据这些参数的意义去分析自己的程序的JVM需要的配置。可以事先做一些尝试,再逐步调优,这个调优也是一个过程,没有足够的经验而做到一步到位是一件很...
  • MySQL优化技巧

    万次阅读 多人点赞 2017-09-10 14:14:00
    MySQL优化三大方向① 优化MySQL所在服务器内核(此优化一般由运维人员完成)。② 对MySQL配置参数进行优化(my.cnf)此优化需要进行压力测试来进行参数调整。③ 对SQL语句以及表优化。MySQL参数优化1:MySQL 默认的最大...
  • 一、一般来说nginx 配置文件中对优化比较作用的为以下几项: 1. worker_processes 8; nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数 (如,2个四核的cpu计为8)。 2. worker_cpu_affinity 00000001...
  • 您可以到这里下载本篇博文所使用的数据库以及优化工具mysqldumpslow和pt-query-digest: https://blog.csdn.net/IT_TIfarmer/article/details/92224646 关于explain语句的结果参数详解也可以参考如上博文...
  • [机器学习] --- 参数优化与模型选择

    千次阅读 2018-07-07 17:06:16
    # SVM的三个超参数:C为惩罚因子,kernel为核函数类型,gamma为核函数的额外参数(对于不同类型的核函数不同的含义) # 别于传统的网格搜索(GridSearch),这里只需要给出最优参数的概率分布即可,而不需要按照...
  • 卷积神经网络(CNN)的参数优化方法

    万次阅读 2019-06-08 19:32:17
    积神经网络的参数优化方法——调整网络结构是关键!!!你只需不停增加层,直到测试误差不再减少. 著名:本文是从 Michael Nielsen的电子书Neural Network and Deep Learning的深度学习那一章的卷积神经网络的参数...
  • 天在做讲课资料的时候遇到一个比较坑的问题。一般来说调用拷贝构造函数分三情况 1.当用类一个对象去初始化另一个对象时。 2.如果函数形参是类对象。 3.如果函数返回值是类对象,函数执行完成返回调用时。 ...
  • 面试官:关于Java性能优化,你什么技巧

    万次阅读 多人点赞 2019-11-27 10:13:05
    一般有两种方案:即优化代码或更改设计方法。我们一般会选择后者,因为不去调用以下代码要比调用一些优化的代码更能提高程序的性能。而一个设计良好的程序能够精简代码,从而提高性能。 下面将提供一些在JAVA程序的...
  • 卷积神经网络参数优化策略(一)

    千次阅读 2020-05-14 11:20:53
    力争用数据给大家一个关于正则化,增加卷积层/全连接数,弃权技术,拓展训练集等参数优化方法的效果。 提高泛化能力的方法,一般来说,提高泛化能力的方法主要以下几个: 正则化 增加神经网络层数 使用正确的代价...
  • 一般有两种情况: 1、内存泄露,对象已经死了,无法通过垃圾收集器进行自动回收,通过找出泄露的代码位置和原因,才好确定解决方案; 2、内存溢出,内存中的对象都还必须存活着,这说明Java堆分配空间不足,检查堆...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 443,132
精华内容 177,252
关键字:

优化参数一般有两种类型