草庐IT

(一)PaddlePaddle(深度学习框架)的搭建、使用

Kkh_8686 2025-05-02 原文

PaddlePaddle是百度公司2016年开源的深度学习框架,现如今可以方便部署到服务器、智能手机和嵌入式设备中。PaddlePaddle还开源大量常用的深度学习模型。

一、PaddlePaddle快速入门:

(1)PaddlePaddle的大部分API都在paddle.fluid中。接着定义两个PaddlePaddle常量x1和x2,形状是[2,2],也叫维度,并赋值为1,类型为int64,得到一个张良[[1,1],[1,1]],代码:


# PaddlePaddle的大部分API都在paddle.fluid中。
import paddle
# 兼容PaddlePaddle2.0
paddle.enable_static()

# 接着定义两个PaddlePaddle常量x1和x2,形状是[22],也叫维度,并赋值为1,类型为int64,得到一个张良[[11][11]]
x1 = fluid.layers.fill_constant(shape=[2, 2], value=1, dtype='int64')
x2 = fluid.layers.fill_constant(shape=[2, 2], value=1, dtype='int64')

# 将x1与x2两个张量相加
# PaddlePaddle支持使用算术运算符号,如改成x1+x2
y1 = fluid.layers.sum(x=[x1, x2])

# 然后创建一个执行器,执行器用于把数据传入模型中,并执行模型中。执行器可以使用place参数指定CPUGPU进行计算
# place = fluid.CUDAPlace(0)         # 使用GPU,其中0是指序号为0的显卡
place = fluid.CPUPlace()             # 使用CPU
exe = fluid.executor.Executor(place)
# 使用fluid.Executor()函数执行fluid.default_startup_program()函数,对整个PaddlePaddle程序进行参数随机初始化
exe.run(fluid.default_startup_program())

# PaddlePaddle中两个程序默认:default_startup_program()、default_main_program()
# 使用fluid.Executor()函数执行,主程序参数值是fluid.default_main_program()
result = exe.run(program=fluid.default_main_program(),
                 fetch_list=[y1])
print(result)

运行结果:

(2)PaddlePaddle定义两个变量,赋值,然后相加:

import paddle.fluid as fluid
import numpy as np
import paddle
# 兼容PaddlePaddle2.0
paddle.enable_static()

# PaddlePaddle的每层又有名称,定义两个张量,不需要指定形状和值,只指定变量的类型和名称(a,b)即可,如不指定名称,会默认设置名称
a = fluid.layers.create_tensor(dtype='int64', name='a')
b = fluid.layers.create_tensor(dtype='int64', name='b')

# 将两个张量求和
y = fluid.layers.sum(x=[a, b])

# 创建一个使用CPU的执行器
place = fluid.CPUPlace()
exe = fluid.executor.Executor(place)
# 进行参数初始化
exe.run(fluid.default_startup_program())

# 用numpy创建两个形状[12]de1矩阵,
a1 = np.array([3, 2]).astype('int64')
b1 = np.array([1, 1]).astype('int64')

# 进行运算,并把y的结果输出
out_a, out_b, result = exe.run(program=fluid.default_main_program(),
                               feed={a.name: a1, b.name: b1},
                               fetch_list=[a, b, y])
print(out_a," + ", out_b," = ", result)

运行结果:

二、PaddlePaddle的线性回归算法:

(1)深度神经网络的搭建:

1、单个神经元的模型就是有多个输入,经过求和、求积计算,然后再经过非线性函数(如ReLU等各种激活函数),最终输出

1、将多个神经元组合在一起,就构成了一个神经网络,依次有输入层、隐藏层、输出层。输入层的每个输入都与隐藏层连接,通过隐藏层计算,最终连接输出层进行输出;
2、在简单的神经网络模型的基础上,再在输入层和输出层之间增加多个隐藏层,会增加整个模型的深度。正因为有大量的隐藏层,所以称为深度神经网络模型;

(2)模型训练

# PaddlePaddle的线性回归算法
import numpy as np
import paddle
paddle.enable_static()
import paddle.fluid as fluid
import numpy

# 搭建一个简单的神经网络(1个输入层,2个隐藏层,1个输出层,即全连接层)
# 定义一个输入层:指定输入层的名称'x',形状和类型。shape的第一个参数是输入数据批量大小通常设置None,这样可以自动根据输入数据的批量大小变动,输入层都是float32类型
x = fluid.data(name='x', shape=[None, 1], dtype='float32')
# 定义两个隐藏层(大小无为100(神经元数量),激活函数为ReLU)
hidden = fluid.layers.fc(input=x, size=100, act='relu')
hidden = fluid.layers.fc(input=hidden, size=100, act='relu')
# 最后输出大小为1的全连接层,也叫输出层
net = fluid.layers.fc(input=hidden, size=1, act=None)

# PaddlePaddle按顺序把深度神经网络模型、损失函数等这些计算添加到主程序中,但此时只复制神经网路模型
infer_program = fluid.default_main_program().clone(for_test=True)

# 定义一个标签层,每个标签层为每组数据对应的真实结果
y = fluid.data(name='y', shape=[None,1], dtype='float32')
# 定义神经网络模型的损失函数,是一个批量的损失
cost = fluid.layers.square_error_cost(input=net, label=y)
# 求平均值
avg_cost = fluid.layers.mean(cost)

# 定义训练的优化方法(SGD随机梯度下降,学习率0.01)
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.01)
opts = optimizer.minimize(avg_cost)

# 创建执行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

# 用numpy定义一组数据,输入层数据:x_data,标签层:y_data(y=2*x+1),程序不知道这个规律,我们进行训练来拟合
x_data = np.array([[1.0], [2.0], [3.0], [4.0], [5.0]]).astype('float32')
y_data = np.array([[3.0], [5.0], [7.0], [9.0], [11.0]]).astype('float32')

for pass_id in range(100):
    train_cost = exe.run(program=fluid.default_main_program(),  # 加载模型
                         feed={x.name:x_data, y.name:y_data},   # 喂入输入数据、真实结果数据
                         fetch_list=[avg_cost])                 # 让执行器在训练中输出损失值
    print("Pass:%d, Cost:%0.5f" % (pass_id, train_cost[0]))

运行结果,模型收敛:

(3)模型预测:

# PaddlePaddle的线性回归算法
# PaddlePaddle的线性回归算法
import numpy as np
import paddle
paddle.enable_static()
import paddle.fluid as fluid
import numpy

# 搭建一个简单的神经网络(1个输入层,2个隐藏层,1个输出层,即全连接层)
# 定义一个输入层:指定输入层的名称'x',形状和类型。shape的第一个参数是输入数据批量大小通常设置None,这样可以自动根据输入数据的批量大小变动,输入层都是float32类型
x = fluid.data(name='x', shape=[None, 1], dtype='float32')
# 定义两个隐藏层(大小无为100(神经元数量),激活函数为ReLU)
hidden = fluid.layers.fc(input=x, size=100, act='relu')
hidden = fluid.layers.fc(input=hidden, size=100, act='relu')
# 最后输出大小为1的全连接层,也叫输出层
net = fluid.layers.fc(input=hidden, size=1, act=None)

# 创建深度神经网络后,可以从主程序复制一个程序与预测数据
# PaddlePaddle按顺序把深度神经网络模型、损失函数等这些计算添加到主程序中,但此时只复制神经网路模型
infer_program = fluid.default_main_program().clone(for_test=True)

# 定义一个标签层,每个标签层为每组数据对应的真实结果
y = fluid.data(name='y', shape=[None,1], dtype='float32')
# 定义神经网络模型的损失函数,是一个批量的损失(cost是通过了神经网络输出的net,与标签为y的方差值)
cost = fluid.layers.square_error_cost(input=net, label=y)
# 求方差平均值
avg_cost = fluid.layers.mean(cost)

# 定义训练的优化方法(SGD随机梯度下降,学习率0.01)
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.005)
opts = optimizer.minimize(avg_cost)

# 创建执行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

# 用numpy定义一组数据,输入层数据:x_data,标签层:y_data(y=2*x+1),程序不知道这个规律,我们进行训练来拟合
x_data = np.array([[1.0], [2.0], [3.0], [4.0], [5.0]]).astype('float32')
y_data = np.array([[3.0], [5.0], [7.0], [9.0], [11.0]]).astype('float32')

for pass_id in range(200):
    train_cost = exe.run(program=fluid.default_main_program(),  # 加载模型
                         feed={x.name:x_data, y.name:y_data},   # 喂入输入数据、真实结果数据(分别把x_data、y_data的值赋给x、y)
                         fetch_list=[avg_cost])                 # 让执行器在训练中输出损失值
    print("Pass:%d, Cost:%0.5f" % (pass_id, train_cost[0]))


test_data = np.array([[6.0]]).astype('float32')
result = exe.run(program=infer_program,
                 feed={x.name:test_data},
                 fetch_list=[net])
print("当x为6.0时,y为:%0.5f:" % result[0])

运行结果:

三、PaddlePaddle卷积神经网络(MNIST手写数字识别):

卷积神经网络一般用于图像特征提取,如图像分类、目标检测、文字识别等。卷积神经网络通常由卷积层、池化层、全连接层组成。

MNIST手写数据集包括6000条训练数据集和1000条测试训练集

# PaddlePaddle卷积神经网络--MNIST手写数字识别
# MNIST手写数据集包括6000条训练数据集和1000条测试训练集
# 图片是28pxX29xp的灰度图像,对应的标签是0`910个数字,每张图片都经过大小归一化和居中处理

import numpy as np
import paddle
paddle.enable_static()
import paddle.dataset.mnist as mnist
import paddle.fluid as fluid
from PIL import Image


# 搭建简单的卷积神经网络:输入层、卷积层、池化层、卷积层、池化层、输出层
def convolutional_neural_netwrk(input):
    # 卷积层(input:数据输入,num_filters:卷积核数量,filter_size:卷积核大小,stride:卷积核滑动步长)
    conv1 = fluid.layers.conv2d(input=input,
                                num_filters=32,
                                filter_size=3,
                                stride=1)
    # 池化层(最大值池化)
    pool1 = fluid.layers.pool2d(input=conv1,
                               pool_size=2,
                               pool_stride=1,
                               pool_type='max')
    conv2 = fluid.layers.conv2d(input=pool1,
                                num_filters=64,
                                filter_size=3,
                                stride=1)
    pool2 = fluid.layers.pool2d(input=conv2,
                               pool_size=2,
                               pool_stride=1,
                               pool_type='max')
    # 全连接层,指定大小为10,因为MNIST数据集的类别数量是10。softmax通过用于分类任务中,每个类别的概率总和为1
    fc = fluid.layers.fc(input=pool2, size=10, act='softmax')
    return fc

# 定义标签层,图像是单通道28pxX28px,所以[1, 28, 28]
image = fluid.data(name='image', shape=[None, 1, 28, 28], dtype='float32')
label = fluid.data(name='label', shape=[None, 1], dtype='int64')

model = convolutional_neural_netwrk(image)
# 在通过深度神经获取输出之后,就可以从主程序中复制一个程序用于训练结束时的预测
infer_program = fluid.default_main_program().clone(for_test=True)

cost = fluid.layers.cross_entropy(input=model, label=label)  # 交叉熵
avg_cost = fluid.layers.mean(cost)  # 求均值
acc = fluid.layers.accuracy(input=model, label=label)  # 准备率

# 从主程序中复制多一个
test_program = fluid.default_main_program().clone(for_test=True)

# 优化器(Adam是一种自适应调整学习率的方法,使用大数据高维空间场景)
optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.0005)
opts = optimizer.minimize(avg_cost)

# 通过mnist.train()、mnist.test()获取训练集、测试集,batch_size把数据集分割一个个批次,一批次数据为128张
train_reader = paddle.batch(mnist.train(), batch_size=128)
test_reader = paddle.batch(mnist.test(), batch_size=128)

# 初始化执行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

# 通过feed_list指定每组数据输入顺序,通过place指定训练数据向CPU输入
feeder = fluid.DataFeeder(place=place, feed_list=[image, label])

# 训练两轮
for pass_id in range(2):
    for batch_id, data in enumerate(train_reader()):
        train_cost, train_acc = exe.run(program=fluid.default_main_program(),
                                        feed=feeder.feed(data),
                                        fetch_list=[avg_cost, acc])
        if batch_id % 100 == 0:
            print('Pass:%d, Batch:%d, Cost:%0.5f, Accuracy:%0.5f' % (pass_id, batch_id, train_cost[0], train_acc[0]))

# 训练结束,再进行一次测试,使用测试集进行测试
test_accs = []
test_costs = []
for batch_id, data in enumerate(test_reader()):
    test_cost, test_acc = exe.run(program=test_program,
                                  feed=feeder.feed(data),
                                  fetch_list=[avg_cost, acc])
    test_costs.append(test_cost[0])
    test_accs.append(test_cost[0])
# 求测试结果的平均值
test_cost = (sum(test_costs) / len(test_costs))
test_acc = (sum(test_accs) / len(test_accs))
print("Test:%d, Cost:%0.5f, Accuracy:%0.5f" % (pass_id, test_cost, test_acc))

训练结果:

识别手写数字8:

代码:

# PaddlePaddle卷积神经网络--MNIST手写数字识别
# MNIST手写数据集包括6000条训练数据集和1000条测试训练集
# 图片是28pxX29xp的灰度图像,对应的标签是0`910个数字,每张图片都经过大小归一化和居中处理

import numpy as np
import paddle
paddle.enable_static()
import paddle.dataset.mnist as mnist
import paddle.fluid as fluid
from PIL import Image


# 搭建简单的卷积神经网络:输入层、卷积层、池化层、卷积层、池化层、输出层
def convolutional_neural_netwrk(input):
    # 卷积层(input:数据输入,num_filters:卷积核数量,filter_size:卷积核大小,stride:卷积核滑动步长)
    conv1 = fluid.layers.conv2d(input=input,
                                num_filters=32,
                                filter_size=3,
                                stride=1)
    # 池化层(最大值池化)
    pool1 = fluid.layers.pool2d(input=conv1,
                               pool_size=2,
                               pool_stride=1,
                               pool_type='max')
    conv2 = fluid.layers.conv2d(input=pool1,
                                num_filters=64,
                                filter_size=3,
                                stride=1)
    pool2 = fluid.layers.pool2d(input=conv2,
                               pool_size=2,
                               pool_stride=1,
                               pool_type='max')
    # 全连接层,指定大小为10,因为MNIST数据集的类别数量是10。softmax通过用于分类任务中,每个类别的概率总和为1
    fc = fluid.layers.fc(input=pool2, size=10, act='softmax')
    return fc

# 定义标签层,图像是单通道28pxX28px,所以[1, 28, 28]
image = fluid.data(name='image', shape=[None, 1, 28, 28], dtype='float32')
label = fluid.data(name='label', shape=[None, 1], dtype='int64')

model = convolutional_neural_netwrk(image)
# 在通过深度神经获取输出之后,就可以从主程序中复制一个程序用于训练结束时的预测
infer_program = fluid.default_main_program().clone(for_test=True)

cost = fluid.layers.cross_entropy(input=model, label=label)  # 交叉熵
avg_cost = fluid.layers.mean(cost)  # 求均值
acc = fluid.layers.accuracy(input=model, label=label)  # 准确率

# 从主程序中复制多一个测试程序,为了能够在测试中输出损失值和准确率
test_program = fluid.default_main_program().clone(for_test=True)

# 优化器(Adam是一种自适应调整学习率的方法,使用大数据高维空间场景)
optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.0005)
opts = optimizer.minimize(avg_cost)

# 通过mnist.train()、mnist.test()获取训练集、测试集,batch_size把数据集分割一个个批次,一批次数据为128张
train_reader = paddle.batch(mnist.train(), batch_size=128)
test_reader = paddle.batch(mnist.test(), batch_size=128)

# 初始化执行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

# 通过feed_list指定每组数据输入顺序,通过place指定训练数据向CPU输入
feeder = fluid.DataFeeder(place=place, feed_list=[image, label])

# 训练两轮
for pass_id in range(2):
    for batch_id, data in enumerate(train_reader()):
        # fetch_list:后面的参数是决定上面功能
        train_cost, train_acc = exe.run(program=fluid.default_main_program(),
                                        feed=feeder.feed(data),
                                        fetch_list=[avg_cost, acc])   # 损失值、准确率
        if batch_id % 100 == 0:
            print('Pass:%d, Batch:%d, Cost:%0.5f, Accuracy:%0.5f' % (pass_id, batch_id, train_cost[0], train_acc[0]))

# 训练结束,再进行一次测试,使用测试集进行测试
test_accs = []
test_costs = []
for batch_id, data in enumerate(test_reader()):
    test_cost, test_acc = exe.run(program=test_program,
                                  feed=feeder.feed(data),
                                  fetch_list=[avg_cost, acc])   # 损失值、准确率
    test_accs.append(test_acc[0])
    test_costs.append(test_cost[0])
# 求测试结果的平均值
test_cost = (sum(test_costs) / len(test_costs))
test_acc = (sum(test_accs) / len(test_accs))
print("Test:%d, Cost:%0.5f, Accuracy:%0.5f" % (pass_id, test_cost, test_acc))

# 上述训练结束,接下来预测一张实际的图片
# 先将图片经过预处理转换成张量加载到PaddlePaddle训练。(灰度化缩放大小)
def load_image(file):
    im = Image.open(file).convert('L')
    im = im.resize((28,28), Image.ANTIALIAS)   # ANTIALIAS:高质量
    im = np.array(im).reshape(1,1,28,28).astype(np.float32)
    im = im / 255.0 * 2.0 - 1.0
    return im

img = load_image('F:\\PyQt_Serial_Assistant_Drive_Detect\\Friuts_Classify\\8.jpg')
results = exe.run(program=infer_program,   # program是上面复制的预测程序
                  feed={image.name:img},   # 只有输入层,为加载的图片
                  fetch_list=[model])      # 为神经网络模型最后的分类器,输出一个分类结果

# np.argsort(results)得到的是每个类别的概率,通过下标找出最大概率测试结果的标签
lab = np.argsort(results)[0][0][-1]
c = np.argsort(results)
print('数字8的image is: %d' % lab)
print(c)

运行结果:

有关(一)PaddlePaddle(深度学习框架)的搭建、使用的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐