Compare commits
1 Commits
create-pul
...
v1.5.0rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1debabb321 |
214
.clang-format
214
.clang-format
@@ -1,214 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: NextLine
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequires: false
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
- ParseTestProto
|
||||
- ParsePartialTestProto
|
||||
CanonicalDelimiter: pb
|
||||
BasedOnStyle: google
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Auto
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
...
|
||||
@@ -1,4 +1,4 @@
|
||||
Checks: 'modernize-*,-modernize-use-nodiscard,-modernize-concat-nested-namespaces,-modernize-make-*,-modernize-use-auto,-modernize-raw-string-literal,-modernize-avoid-c-arrays,-modernize-use-trailing-return-type,google-*,-google-default-arguments,-clang-diagnostic-#pragma-messages,readability-identifier-naming'
|
||||
Checks: 'modernize-*,-modernize-make-*,-modernize-use-auto,-modernize-raw-string-literal,-modernize-avoid-c-arrays,-modernize-use-trailing-return-type,google-*,-google-default-arguments,-clang-diagnostic-#pragma-messages,readability-identifier-naming'
|
||||
CheckOptions:
|
||||
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
|
||||
- { key: readability-identifier-naming.StructCase, value: CamelCase }
|
||||
|
||||
18
.gitattributes
vendored
18
.gitattributes
vendored
@@ -1,18 +0,0 @@
|
||||
* text=auto
|
||||
|
||||
*.c text eol=lf
|
||||
*.h text eol=lf
|
||||
*.cc text eol=lf
|
||||
*.cuh text eol=lf
|
||||
*.cu text eol=lf
|
||||
*.py text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.R text eol=lf
|
||||
*.scala text eol=lf
|
||||
*.java text eol=lf
|
||||
|
||||
*.sh text eol=lf
|
||||
|
||||
*.rst text eol=lf
|
||||
*.md text eol=lf
|
||||
*.csv text eol=lf
|
||||
31
.github/dependabot.yml
vendored
31
.github/dependabot.yml
vendored
@@ -1,31 +0,0 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/jvm-packages"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/jvm-packages/xgboost4j"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/jvm-packages/xgboost4j-gpu"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/jvm-packages/xgboost4j-example"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/jvm-packages/xgboost4j-spark"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/jvm-packages/xgboost4j-spark-gpu"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
29
.github/workflows/jvm_tests.yml
vendored
29
.github/workflows/jvm_tests.yml
vendored
@@ -2,9 +2,6 @@ name: XGBoost-JVM-Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
test-with-jvm:
|
||||
name: Test JVM on OS ${{ matrix.os }}
|
||||
@@ -12,19 +9,19 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-11]
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a # v4.3.0
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.8'
|
||||
architecture: 'x64'
|
||||
|
||||
- uses: actions/setup-java@d202f5dbf7256730fb690ec59f6381650114feb2 # v3.6.0
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
@@ -34,13 +31,13 @@ jobs:
|
||||
python -m pip install awscli
|
||||
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@6998d139ddd3e68c71e9e398d8e40b71a2f39812 # v3.2.5
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('./jvm-packages/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-m2-${{ hashFiles('./jvm-packages/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-m2
|
||||
|
||||
- name: Test XGBoost4J (Core)
|
||||
- name: Test XGBoost4J
|
||||
run: |
|
||||
cd jvm-packages
|
||||
mvn test -B -pl :xgboost4j_2.12
|
||||
@@ -67,7 +64,7 @@ jobs:
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_IAM_S3_UPLOADER }}
|
||||
|
||||
|
||||
- name: Test XGBoost4J (Core, Spark, Examples)
|
||||
- name: Test XGBoost4J-Spark
|
||||
run: |
|
||||
rm -rfv build/
|
||||
cd jvm-packages
|
||||
@@ -75,13 +72,3 @@ jobs:
|
||||
if: matrix.os == 'ubuntu-latest' # Distributed training doesn't work on Windows
|
||||
env:
|
||||
RABIT_MOCK: ON
|
||||
|
||||
|
||||
- name: Build and Test XGBoost4J with scala 2.13
|
||||
run: |
|
||||
rm -rfv build/
|
||||
cd jvm-packages
|
||||
mvn -B clean install test -Pdefault,scala-2.13
|
||||
if: matrix.os == 'ubuntu-latest' # Distributed training doesn't work on Windows
|
||||
env:
|
||||
RABIT_MOCK: ON
|
||||
|
||||
142
.github/workflows/main.yml
vendored
142
.github/workflows/main.yml
vendored
@@ -6,9 +6,6 @@ name: XGBoost-CI
|
||||
# events but only for the master branch
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
gtest-cpu:
|
||||
@@ -17,14 +14,17 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-11]
|
||||
os: [macos-10.15]
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
# Use libomp 11.1.0: https://github.com/dmlc/xgboost/issues/7039
|
||||
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/679923b4eb48a8dc7ecc1f05d06063cd79b3fc00/Formula/libomp.rb -O $(find $(brew --repository) -name libomp.rb)
|
||||
brew install ninja libomp
|
||||
brew pin libomp
|
||||
- name: Build gtest binary
|
||||
run: |
|
||||
mkdir build
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install system packages
|
||||
@@ -66,30 +66,30 @@ jobs:
|
||||
c-api-demo:
|
||||
name: Test installing XGBoost lib + building the C API demo
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -l {0}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ["ubuntu-latest"]
|
||||
python-version: ["3.8"]
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: mamba-org/provision-with-micromamba@f347426e5745fe3dfc13ec5baf20496990d0281f # v14
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends ninja-build
|
||||
- uses: conda-incubator/setup-miniconda@v2
|
||||
with:
|
||||
cache-downloads: true
|
||||
cache-env: true
|
||||
environment-name: cpp_test
|
||||
environment-file: tests/ci_build/conda_env/cpp_test.yml
|
||||
auto-update-conda: true
|
||||
python-version: ${{ matrix.python-version }}
|
||||
activate-environment: test
|
||||
- name: Display Conda env
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
|
||||
- name: Build and install XGBoost static library
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
@@ -97,6 +97,7 @@ jobs:
|
||||
ninja -v install
|
||||
cd -
|
||||
- name: Build and run C API demo with static
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
pushd .
|
||||
cd demo/c-api/
|
||||
@@ -108,14 +109,15 @@ jobs:
|
||||
cd ..
|
||||
rm -rf ./build
|
||||
popd
|
||||
|
||||
- name: Build and install XGBoost shared library
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
cd build
|
||||
cmake .. -DBUILD_STATIC_LIB=OFF -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -GNinja
|
||||
ninja -v install
|
||||
cd -
|
||||
- name: Build and run C API demo with shared
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
pushd .
|
||||
cd demo/c-api/
|
||||
@@ -128,31 +130,103 @@ jobs:
|
||||
./tests/ci_build/verify_link.sh ./demo/c-api/build/basic/api-demo
|
||||
./tests/ci_build/verify_link.sh ./demo/c-api/build/external-memory/external-memory-demo
|
||||
|
||||
cpp-lint:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: Code linting for C++
|
||||
name: Code linting for Python and C++
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a # v4.3.0
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.8"
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
- name: Install Python packages
|
||||
run: |
|
||||
python -m pip install wheel setuptools cpplint pylint
|
||||
python -m pip install wheel setuptools
|
||||
python -m pip install pylint cpplint numpy scipy scikit-learn
|
||||
- name: Run lint
|
||||
run: |
|
||||
python3 dmlc-core/scripts/lint.py xgboost cpp R-package/src
|
||||
make lint
|
||||
|
||||
python3 dmlc-core/scripts/lint.py --exclude_path \
|
||||
python-package/xgboost/dmlc-core \
|
||||
python-package/xgboost/include \
|
||||
python-package/xgboost/lib \
|
||||
python-package/xgboost/rabit \
|
||||
python-package/xgboost/src \
|
||||
--pylint-rc python-package/.pylintrc \
|
||||
xgboost \
|
||||
cpp \
|
||||
include src python-package
|
||||
mypy:
|
||||
runs-on: ubuntu-latest
|
||||
name: Type checking for Python
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
- name: Install Python packages
|
||||
run: |
|
||||
python -m pip install wheel setuptools mypy pandas dask[complete] distributed
|
||||
- name: Run mypy
|
||||
run: |
|
||||
make mypy
|
||||
|
||||
doxygen:
|
||||
runs-on: ubuntu-latest
|
||||
name: Generate C/C++ API doc using Doxygen
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends doxygen graphviz ninja-build
|
||||
python -m pip install wheel setuptools
|
||||
python -m pip install awscli
|
||||
- name: Run Doxygen
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DBUILD_C_DOC=ON -GNinja
|
||||
ninja -v doc_doxygen
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||
id: extract_branch
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
- name: Publish
|
||||
run: |
|
||||
cd build/
|
||||
tar cvjf ${{ steps.extract_branch.outputs.branch }}.tar.bz2 doc_doxygen/
|
||||
python -m awscli s3 cp ./${{ steps.extract_branch.outputs.branch }}.tar.bz2 s3://xgboost-docs/doxygen/ --acl public-read
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_IAM_S3_UPLOADER }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_IAM_S3_UPLOADER }}
|
||||
|
||||
sphinx:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build docs using Sphinx
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.8'
|
||||
architecture: 'x64'
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends graphviz
|
||||
python -m pip install wheel setuptools
|
||||
python -m pip install -r doc/requirements.txt
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||
id: extract_branch
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
- name: Run Sphinx
|
||||
run: |
|
||||
make -C doc html
|
||||
env:
|
||||
SPHINX_GIT_BRANCH: ${{ steps.extract_branch.outputs.branch }}
|
||||
|
||||
270
.github/workflows/python_tests.yml
vendored
270
.github/workflows/python_tests.yml
vendored
@@ -2,297 +2,93 @@ name: XGBoost-Python-Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -l {0}
|
||||
|
||||
jobs:
|
||||
python-mypy-lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: Type and format checks for the Python package
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: mamba-org/provision-with-micromamba@f347426e5745fe3dfc13ec5baf20496990d0281f # v14
|
||||
with:
|
||||
cache-downloads: true
|
||||
cache-env: true
|
||||
environment-name: python_lint
|
||||
environment-file: tests/ci_build/conda_env/python_lint.yml
|
||||
- name: Display Conda env
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
- name: Run mypy
|
||||
run: |
|
||||
python tests/ci_build/lint_python.py --format=0 --type-check=1 --pylint=0
|
||||
- name: Run formatter
|
||||
run: |
|
||||
python tests/ci_build/lint_python.py --format=1 --type-check=0 --pylint=0
|
||||
- name: Run pylint
|
||||
run: |
|
||||
python tests/ci_build/lint_python.py --format=0 --type-check=0 --pylint=1
|
||||
|
||||
python-sdist-test-on-Linux:
|
||||
# Mismatched glibcxx version between system and conda forge.
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Test installing XGBoost Python source package on ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
with:
|
||||
submodules: 'true'
|
||||
- uses: mamba-org/provision-with-micromamba@f347426e5745fe3dfc13ec5baf20496990d0281f # v14
|
||||
with:
|
||||
cache-downloads: true
|
||||
cache-env: true
|
||||
environment-name: sdist_test
|
||||
environment-file: tests/ci_build/conda_env/sdist_test.yml
|
||||
- name: Display Conda env
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
- name: Build and install XGBoost
|
||||
run: |
|
||||
cd python-package
|
||||
python --version
|
||||
python -m build --sdist
|
||||
pip install -v ./dist/xgboost-*.tar.gz --config-settings use_openmp=False
|
||||
cd ..
|
||||
python -c 'import xgboost'
|
||||
|
||||
python-sdist-test:
|
||||
# Use system toolchain instead of conda toolchain for macos and windows.
|
||||
# MacOS has linker error if clang++ from conda-forge is used
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Test installing XGBoost Python source package on ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-11, windows-latest]
|
||||
os: [ubuntu-latest, macos-10.15, windows-latest]
|
||||
python-version: ["3.8"]
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install osx system dependencies
|
||||
if: matrix.os == 'macos-11'
|
||||
if: matrix.os == 'macos-10.15'
|
||||
run: |
|
||||
# Use libomp 11.1.0: https://github.com/dmlc/xgboost/issues/7039
|
||||
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/679923b4eb48a8dc7ecc1f05d06063cd79b3fc00/Formula/libomp.rb -O $(find $(brew --repository) -name libomp.rb)
|
||||
brew install ninja libomp
|
||||
- uses: conda-incubator/setup-miniconda@35d1405e78aa3f784fe3ce9a2eb378d5eeb62169 # v2.1.1
|
||||
brew pin libomp
|
||||
- name: Install Ubuntu system dependencies
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends ninja-build
|
||||
- uses: conda-incubator/setup-miniconda@v2
|
||||
with:
|
||||
auto-update-conda: true
|
||||
python-version: ${{ matrix.python-version }}
|
||||
activate-environment: test
|
||||
- name: Install build
|
||||
run: |
|
||||
conda install -c conda-forge python-build
|
||||
- name: Display Conda env
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
- name: Build and install XGBoost
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
cd python-package
|
||||
python --version
|
||||
python -m build --sdist
|
||||
python setup.py sdist
|
||||
pip install -v ./dist/xgboost-*.tar.gz
|
||||
cd ..
|
||||
python -c 'import xgboost'
|
||||
|
||||
python-tests-on-macos:
|
||||
python-tests:
|
||||
name: Test XGBoost Python package on ${{ matrix.config.os }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: macos-11}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- uses: mamba-org/provision-with-micromamba@f347426e5745fe3dfc13ec5baf20496990d0281f # v14
|
||||
with:
|
||||
cache-downloads: true
|
||||
cache-env: true
|
||||
environment-name: macos_test
|
||||
environment-file: tests/ci_build/conda_env/macos_cpu_test.yml
|
||||
|
||||
- name: Display Conda env
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
|
||||
- name: Build XGBoost on macos
|
||||
run: |
|
||||
brew install ninja
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
# Set prefix, to use OpenMP library from Conda env
|
||||
# See https://github.com/dmlc/xgboost/issues/7039#issuecomment-1025038228
|
||||
# to learn why we don't use libomp from Homebrew.
|
||||
cmake .. -GNinja -DCMAKE_PREFIX_PATH=$CONDA_PREFIX
|
||||
ninja
|
||||
|
||||
- name: Install Python package
|
||||
run: |
|
||||
cd python-package
|
||||
python --version
|
||||
pip install -v .
|
||||
|
||||
- name: Test Python package
|
||||
run: |
|
||||
pytest -s -v -rxXs --durations=0 ./tests/python
|
||||
|
||||
- name: Test Dask Interface
|
||||
run: |
|
||||
pytest -s -v -rxXs --durations=0 ./tests/test_distributed/test_with_dask
|
||||
|
||||
python-tests-on-win:
|
||||
name: Test XGBoost Python package on ${{ matrix.config.os }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: windows-latest, python-version: '3.8'}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- uses: conda-incubator/setup-miniconda@35d1405e78aa3f784fe3ce9a2eb378d5eeb62169 # v2.1.1
|
||||
with:
|
||||
auto-update-conda: true
|
||||
python-version: ${{ matrix.config.python-version }}
|
||||
activate-environment: win64_env
|
||||
environment-file: tests/ci_build/conda_env/win64_cpu_test.yml
|
||||
|
||||
- name: Display Conda env
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
|
||||
- name: Build XGBoost on Windows
|
||||
run: |
|
||||
mkdir build_msvc
|
||||
cd build_msvc
|
||||
cmake .. -G"Visual Studio 17 2022" -DCMAKE_CONFIGURATION_TYPES="Release" -A x64 -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON
|
||||
cmake --build . --config Release --parallel $(nproc)
|
||||
|
||||
- name: Install Python package
|
||||
run: |
|
||||
cd python-package
|
||||
python --version
|
||||
pip wheel -v . --wheel-dir dist/
|
||||
pip install ./dist/*.whl
|
||||
|
||||
- name: Test Python package
|
||||
run: |
|
||||
pytest -s -v -rxXs --durations=0 ./tests/python
|
||||
|
||||
python-tests-on-ubuntu:
|
||||
name: Test XGBoost Python package on ${{ matrix.config.os }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: ubuntu-latest, python-version: "3.8"}
|
||||
- {os: windows-2016, compiler: 'msvc', python-version: '3.8'}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- uses: mamba-org/provision-with-micromamba@f347426e5745fe3dfc13ec5baf20496990d0281f # v14
|
||||
- uses: conda-incubator/setup-miniconda@v2
|
||||
with:
|
||||
cache-downloads: true
|
||||
cache-env: true
|
||||
environment-name: linux_cpu_test
|
||||
environment-file: tests/ci_build/conda_env/linux_cpu_test.yml
|
||||
auto-update-conda: true
|
||||
python-version: ${{ matrix.config.python-version }}
|
||||
activate-environment: win64_test
|
||||
environment-file: tests/ci_build/conda_env/win64_cpu_test.yml
|
||||
|
||||
- name: Display Conda env
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
conda info
|
||||
conda list
|
||||
|
||||
- name: Build XGBoost on Ubuntu
|
||||
- name: Build XGBoost with msvc
|
||||
shell: bash -l {0}
|
||||
if: matrix.config.compiler == 'msvc'
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -GNinja -DCMAKE_PREFIX_PATH=$CONDA_PREFIX
|
||||
ninja
|
||||
mkdir build_msvc
|
||||
cd build_msvc
|
||||
cmake .. -G"Visual Studio 15 2017" -DCMAKE_CONFIGURATION_TYPES="Release" -A x64 -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON
|
||||
cmake --build . --config Release --parallel $(nproc)
|
||||
|
||||
- name: Install Python package
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
cd python-package
|
||||
python --version
|
||||
pip install -v .
|
||||
python setup.py bdist_wheel --universal
|
||||
pip install ./dist/*.whl
|
||||
|
||||
- name: Test Python package
|
||||
run: |
|
||||
pytest -s -v -rxXs --durations=0 ./tests/python
|
||||
|
||||
- name: Test Dask Interface
|
||||
run: |
|
||||
pytest -s -v -rxXs --durations=0 ./tests/test_distributed/test_with_dask
|
||||
|
||||
- name: Test PySpark Interface
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
pytest -s -v -rxXs --durations=0 ./tests/test_distributed/test_with_spark
|
||||
|
||||
python-system-installation-on-ubuntu:
|
||||
name: Test XGBoost Python package System Installation on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
|
||||
- name: Install ninja
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install -y ninja-build
|
||||
|
||||
- name: Build XGBoost on Ubuntu
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -GNinja
|
||||
ninja
|
||||
|
||||
- name: Copy lib to system lib
|
||||
run: |
|
||||
cp lib/* "$(python -c 'import sys; print(sys.base_prefix)')/lib"
|
||||
|
||||
- name: Install XGBoost in Virtual Environment
|
||||
run: |
|
||||
cd python-package
|
||||
pip install virtualenv
|
||||
virtualenv venv
|
||||
source venv/bin/activate && \
|
||||
pip install -v . --config-settings use_system_libxgboost=True && \
|
||||
python -c 'import xgboost'
|
||||
pytest -s -v ./tests/python
|
||||
|
||||
41
.github/workflows/python_wheels.yml
vendored
41
.github/workflows/python_wheels.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: XGBoost-Python-Wheels
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
python-wheels:
|
||||
name: Build wheel for ${{ matrix.platform_id }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-latest
|
||||
platform_id: macosx_x86_64
|
||||
- os: macos-latest
|
||||
platform_id: macosx_arm64
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a # v4.3.0
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Build wheels
|
||||
run: bash tests/ci_build/build_python_wheels.sh ${{ matrix.platform_id }} ${{ github.sha }}
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||
id: extract_branch
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
- name: Upload Python wheel
|
||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
|
||||
run: |
|
||||
python -m pip install awscli
|
||||
python -m awscli s3 cp wheelhouse/*.whl s3://xgboost-nightly-builds/${{ steps.extract_branch.outputs.branch }}/ --acl public-read
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_IAM_S3_UPLOADER }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_IAM_S3_UPLOADER }}
|
||||
22
.github/workflows/r_nold.yml
vendored
22
.github/workflows/r_nold.yml
vendored
@@ -1,4 +1,4 @@
|
||||
# Run expensive R tests with the help of rhub. Only triggered by a pull request review
|
||||
# Run R tests with noLD R. Only triggered by a pull request review
|
||||
# See discussion at https://github.com/dmlc/xgboost/pull/6378
|
||||
|
||||
name: XGBoost-R-noLD
|
||||
@@ -7,30 +7,34 @@ on:
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
env:
|
||||
R_PACKAGES: c('XML', 'igraph', 'data.table', 'ggplot2', 'DiagrammeR', 'Ckmeans.1d.dp', 'vcd', 'testthat', 'lintr', 'knitr', 'rmarkdown', 'e1071', 'cplm', 'devtools', 'float', 'titanic')
|
||||
|
||||
jobs:
|
||||
test-R-noLD:
|
||||
if: github.event.comment.body == '/gha run r-nold-test' && contains('OWNER,MEMBER,COLLABORATOR', github.event.comment.author_association)
|
||||
timeout-minutes: 120
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: rhub/debian-gcc-devel-nold
|
||||
container: rhub/debian-gcc-devel-nold
|
||||
steps:
|
||||
- name: Install git and system packages
|
||||
shell: bash
|
||||
run: |
|
||||
apt update && apt install libcurl4-openssl-dev libssl-dev libssh2-1-dev libgit2-dev libglpk-dev libxml2-dev libharfbuzz-dev libfribidi-dev git -y
|
||||
apt-get update && apt-get install -y git libcurl4-openssl-dev libssl-dev libssh2-1-dev libgit2-dev libxml2-dev
|
||||
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash -l {0}
|
||||
shell: bash
|
||||
run: |
|
||||
/tmp/R-devel/bin/Rscript -e "source('./R-package/tests/helper_scripts/install_deps.R')"
|
||||
cat > install_libs.R <<EOT
|
||||
install.packages(${{ env.R_PACKAGES }},
|
||||
repos = 'http://cloud.r-project.org',
|
||||
dependencies = c('Depends', 'Imports', 'LinkingTo'))
|
||||
EOT
|
||||
/tmp/R-devel/bin/Rscript install_libs.R
|
||||
|
||||
- name: Run R tests
|
||||
shell: bash
|
||||
|
||||
127
.github/workflows/r_tests.yml
vendored
127
.github/workflows/r_tests.yml
vendored
@@ -3,11 +3,9 @@ name: XGBoost-R-Tests
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
R_PACKAGES: c('XML', 'igraph', 'data.table', 'ggplot2', 'DiagrammeR', 'Ckmeans.1d.dp', 'vcd', 'testthat', 'lintr', 'knitr', 'rmarkdown', 'e1071', 'cplm', 'devtools', 'float', 'titanic')
|
||||
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
lintr:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
@@ -15,121 +13,126 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: ubuntu-latest, r: 'release'}
|
||||
- {os: windows-latest, r: 'release', compiler: 'mingw', build: 'autotools'}
|
||||
env:
|
||||
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
|
||||
RSPM: ${{ matrix.config.rspm }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- uses: r-lib/actions/setup-r@50d1eae9b8da0bb3f8582c59a5b82225fa2fe7f2 # v2.3.1
|
||||
- uses: r-lib/actions/setup-r@master
|
||||
with:
|
||||
r-version: ${{ matrix.config.r }}
|
||||
|
||||
- name: Cache R packages
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed # v3.0.11
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.R_LIBS_USER }}
|
||||
key: ${{ runner.os }}-r-${{ matrix.config.r }}-6-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-6-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
key: ${{ runner.os }}-r-${{ matrix.config.r }}-2-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-2-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: Rscript {0}
|
||||
run: |
|
||||
source("./R-package/tests/helper_scripts/install_deps.R")
|
||||
install.packages(${{ env.R_PACKAGES }},
|
||||
repos = 'http://cloud.r-project.org',
|
||||
dependencies = c('Depends', 'Imports', 'LinkingTo'))
|
||||
|
||||
- name: Run lintr
|
||||
run: |
|
||||
MAKEFLAGS="-j$(nproc)" R CMD INSTALL R-package/
|
||||
Rscript tests/ci_build/lint_r.R $(pwd)
|
||||
cd R-package
|
||||
R.exe CMD INSTALL .
|
||||
Rscript.exe tests/helper_scripts/run_lint.R
|
||||
|
||||
test-R-on-Windows:
|
||||
test-with-R:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
name: Test R on OS ${{ matrix.config.os }}, R ${{ matrix.config.r }}, Compiler ${{ matrix.config.compiler }}, Build ${{ matrix.config.build }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {os: windows-latest, r: 'release', compiler: 'mingw', build: 'autotools'}
|
||||
- {os: windows-latest, r: '4.2.0', compiler: 'msvc', build: 'cmake'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'mingw', build: 'autotools'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'msvc', build: 'cmake'}
|
||||
- {os: windows-2016, r: 'release', compiler: 'mingw', build: 'cmake'}
|
||||
env:
|
||||
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
|
||||
RSPM: ${{ matrix.config.rspm }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- uses: r-lib/actions/setup-r@50d1eae9b8da0bb3f8582c59a5b82225fa2fe7f2 # v2.3.1
|
||||
- uses: r-lib/actions/setup-r@master
|
||||
with:
|
||||
r-version: ${{ matrix.config.r }}
|
||||
|
||||
- name: Cache R packages
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed # v3.0.11
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.R_LIBS_USER }}
|
||||
key: ${{ runner.os }}-r-${{ matrix.config.r }}-6-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-6-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
|
||||
- uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a # v4.3.0
|
||||
with:
|
||||
python-version: "3.8"
|
||||
architecture: 'x64'
|
||||
|
||||
- uses: r-lib/actions/setup-tinytex@v2
|
||||
key: ${{ runner.os }}-r-${{ matrix.config.r }}-2-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-2-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: Rscript {0}
|
||||
run: |
|
||||
source("./R-package/tests/helper_scripts/install_deps.R")
|
||||
install.packages(${{ env.R_PACKAGES }},
|
||||
repos = 'http://cloud.r-project.org',
|
||||
dependencies = c('Depends', 'Imports', 'LinkingTo'))
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.7'
|
||||
architecture: 'x64'
|
||||
|
||||
- name: Test R
|
||||
run: |
|
||||
python tests/ci_build/test_r_package.py --compiler='${{ matrix.config.compiler }}' --build-tool="${{ matrix.config.build }}" --task=check
|
||||
python tests/ci_build/test_r_package.py --compiler="${{ matrix.config.compiler }}" --build-tool="${{ matrix.config.build }}"
|
||||
|
||||
test-R-on-Debian:
|
||||
name: Test R package on Debian
|
||||
test-R-CRAN:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: rhub/debian-gcc-devel
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {r: 'release'}
|
||||
|
||||
steps:
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
# Must run before checkout to have the latest git installed.
|
||||
# No need to add pandoc, the container has it figured out.
|
||||
apt update && apt install libcurl4-openssl-dev libssl-dev libssh2-1-dev libgit2-dev libglpk-dev libxml2-dev libharfbuzz-dev libfribidi-dev git -y
|
||||
|
||||
- name: Trust git cloning project sources
|
||||
run: |
|
||||
git config --global --add safe.directory "${GITHUB_WORKSPACE}"
|
||||
|
||||
- uses: actions/checkout@e2f20e631ae6d7dd3b768f56a5d2af784dd54791 # v2.5.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
/tmp/R-devel/bin/Rscript -e "source('./R-package/tests/helper_scripts/install_deps.R')"
|
||||
|
||||
- name: Test R
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
python3 tests/ci_build/test_r_package.py --r=/tmp/R-devel/bin/R --build-tool=autotools --task=check
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: changes
|
||||
- uses: r-lib/actions/setup-r@master
|
||||
with:
|
||||
filters: |
|
||||
r_package:
|
||||
- 'R-package/**'
|
||||
r-version: ${{ matrix.config.r }}
|
||||
|
||||
- name: Run document check
|
||||
if: steps.changes.outputs.r_package == 'true'
|
||||
- uses: r-lib/actions/setup-tinytex@master
|
||||
|
||||
- name: Install system packages
|
||||
run: |
|
||||
python3 tests/ci_build/test_r_package.py --r=/tmp/R-devel/bin/R --task=doc
|
||||
sudo apt-get update && sudo apt-get install libcurl4-openssl-dev libssl-dev libssh2-1-dev libgit2-dev pandoc pandoc-citeproc
|
||||
|
||||
- name: Cache R packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.R_LIBS_USER }}
|
||||
key: ${{ runner.os }}-r-${{ matrix.config.r }}-2-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-2-${{ hashFiles('R-package/DESCRIPTION') }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: Rscript {0}
|
||||
run: |
|
||||
install.packages(${{ env.R_PACKAGES }},
|
||||
repos = 'http://cloud.r-project.org',
|
||||
dependencies = c('Depends', 'Imports', 'LinkingTo'))
|
||||
|
||||
- name: Check R Package
|
||||
run: |
|
||||
# Print stacktrace upon success of failure
|
||||
make Rcheck || tests/ci_build/print_r_stacktrace.sh fail
|
||||
tests/ci_build/print_r_stacktrace.sh success
|
||||
|
||||
54
.github/workflows/scorecards.yml
vendored
54
.github/workflows/scorecards.yml
vendored
@@ -1,54 +0,0 @@
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
- cron: '17 2 * * 6'
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Used to receive a badge.
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # tag=v3.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # tag=v2.0.6
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
||||
# Publish the results for public repositories to enable scorecard badges. For more details, see
|
||||
# https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories, `publish_results` will automatically be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # tag=v3.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # tag=v1.0.26
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
44
.github/workflows/update_rapids.yml
vendored
44
.github/workflows/update_rapids.yml
vendored
@@ -1,44 +0,0 @@
|
||||
name: update-rapids
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 20 * * *" # Run once daily
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -l {0}
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # To use GitHub CLI
|
||||
|
||||
jobs:
|
||||
update-rapids:
|
||||
name: Check latest RAPIDS
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Check latest RAPIDS and update conftest.sh
|
||||
run: |
|
||||
bash tests/buildkite/update-rapids.sh
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
if: github.ref == 'refs/heads/master'
|
||||
with:
|
||||
add-paths: |
|
||||
tests/buildkite
|
||||
branch: create-pull-request/update-rapids
|
||||
base: master
|
||||
title: "[CI] Update RAPIDS to latest stable"
|
||||
commit-message: "[CI] Update RAPIDS to latest stable"
|
||||
|
||||
28
.gitignore
vendored
28
.gitignore
vendored
@@ -52,8 +52,6 @@ Debug
|
||||
R-package.Rproj
|
||||
*.cache*
|
||||
.mypy_cache/
|
||||
doxygen
|
||||
|
||||
# java
|
||||
java/xgboost4j/target
|
||||
java/xgboost4j/tmp
|
||||
@@ -65,7 +63,6 @@ nb-configuration*
|
||||
# Eclipse
|
||||
.project
|
||||
.cproject
|
||||
.classpath
|
||||
.pydevproject
|
||||
.settings/
|
||||
build
|
||||
@@ -99,11 +96,8 @@ metastore_db
|
||||
R-package/src/Makevars
|
||||
*.lib
|
||||
|
||||
# Visual Studio
|
||||
.vs/
|
||||
CMakeSettings.json
|
||||
*.ilk
|
||||
*.pdb
|
||||
# Visual Studio Code
|
||||
/.vscode/
|
||||
|
||||
# IntelliJ/CLion
|
||||
.idea
|
||||
@@ -131,21 +125,3 @@ credentials.csv
|
||||
*.pub
|
||||
*.rdp
|
||||
*_rsa
|
||||
|
||||
# Visual Studio code + extensions
|
||||
.vscode
|
||||
.metals
|
||||
.bloop
|
||||
|
||||
# python tests
|
||||
demo/**/*.txt
|
||||
*.dmatrix
|
||||
.hypothesis
|
||||
__MACOSX/
|
||||
model*.json
|
||||
|
||||
# R tests
|
||||
*.libsvm
|
||||
*.rds
|
||||
Rplots.pdf
|
||||
*.zip
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -2,6 +2,9 @@
|
||||
path = dmlc-core
|
||||
url = https://github.com/dmlc/dmlc-core
|
||||
branch = main
|
||||
[submodule "cub"]
|
||||
path = cub
|
||||
url = https://github.com/NVlabs/cub
|
||||
[submodule "gputreeshap"]
|
||||
path = gputreeshap
|
||||
url = https://github.com/rapidsai/gputreeshap.git
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
submodules:
|
||||
include: all
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.8"
|
||||
apt_packages:
|
||||
- graphviz
|
||||
- cmake
|
||||
- g++
|
||||
- doxygen
|
||||
- ninja-build
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: doc/conf.py
|
||||
|
||||
# If using Sphinx, optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally declare the Python requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- requirements: doc/requirements.txt
|
||||
system_packages: true
|
||||
63
.travis.yml
Normal file
63
.travis.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
sudo: required
|
||||
|
||||
dist: bionic
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "lqkL5SCM/CBwgVb1GWoOngpojsa0zCSGcvF0O3/45rBT1EpNYtQ4LRJ1+XcHi126vdfGoim/8i7AQhn5eOgmZI8yAPBeoUZ5zSrejD3RUpXr2rXocsvRRP25Z4mIuAGHD9VAHtvTdhBZRVV818W02pYduSzAeaY61q/lU3xmWsE="
|
||||
- secure: "mzms6X8uvdhRWxkPBMwx+mDl3d+V1kUpZa7UgjT+dr4rvZMzvKtjKp/O0JZZVogdgZjUZf444B98/7AvWdSkGdkfz2QdmhWmXzNPfNuHtmfCYMdijsgFIGLuD3GviFL/rBiM2vgn32T3QqFiEJiC5StparnnXimPTc9TpXQRq5c="
|
||||
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- os: osx
|
||||
arch: amd64
|
||||
osx_image: xcode10.2
|
||||
env: TASK=python_test
|
||||
- os: osx
|
||||
arch: amd64
|
||||
osx_image: xcode10.2
|
||||
env: TASK=java_test
|
||||
- os: linux
|
||||
arch: s390x
|
||||
env: TASK=s390x_test
|
||||
|
||||
# dependent brew packages
|
||||
# the dependencies from homebrew is installed manually from setup script due to outdated image from travis.
|
||||
addons:
|
||||
homebrew:
|
||||
update: false
|
||||
apt:
|
||||
packages:
|
||||
- unzip
|
||||
|
||||
before_install:
|
||||
- source tests/travis/travis_setup_env.sh
|
||||
- if [ "${TASK}" != "python_sdist_test" ]; then export PYTHONPATH=${PYTHONPATH}:${PWD}/python-package; fi
|
||||
- echo "MAVEN_OPTS='-Xmx2g -XX:MaxPermSize=1024m -XX:ReservedCodeCacheSize=512m -Dorg.slf4j.simpleLogger.defaultLogLevel=error'" > ~/.mavenrc
|
||||
|
||||
install:
|
||||
- source tests/travis/setup.sh
|
||||
|
||||
script:
|
||||
- tests/travis/run_test.sh
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- ${HOME}/.cache/usr
|
||||
- ${HOME}/.cache/pip
|
||||
|
||||
before_cache:
|
||||
- tests/travis/travis_before_cache.sh
|
||||
|
||||
after_failure:
|
||||
- tests/travis/travis_after_failure.sh
|
||||
|
||||
after_success:
|
||||
- tree build
|
||||
- bash <(curl -s https://codecov.io/bash) -a '-o src/ src/*.c'
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: always
|
||||
@@ -1,10 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
|
||||
project(xgboost LANGUAGES CXX C VERSION 2.0.0)
|
||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
||||
project(xgboost LANGUAGES CXX C VERSION 1.5.0)
|
||||
include(cmake/Utils.cmake)
|
||||
list(APPEND CMAKE_MODULE_PATH "${xgboost_SOURCE_DIR}/cmake/modules")
|
||||
cmake_policy(SET CMP0022 NEW)
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
cmake_policy(SET CMP0076 NEW)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
@@ -29,7 +28,6 @@ set_default_configuration_release()
|
||||
option(BUILD_C_DOC "Build documentation for C APIs using Doxygen." OFF)
|
||||
option(USE_OPENMP "Build with OpenMP support." ON)
|
||||
option(BUILD_STATIC_LIB "Build static library" OFF)
|
||||
option(FORCE_SHARED_CRT "Build with dynamic CRT on Windows (/MD)" OFF)
|
||||
option(RABIT_BUILD_MPI "Build MPI" OFF)
|
||||
## Bindings
|
||||
option(JVM_BINDINGS "Build JVM bindings" OFF)
|
||||
@@ -47,11 +45,11 @@ option(USE_NVTX "Build with cuda profiling annotations. Developers only." OFF)
|
||||
set(NVTX_HEADER_DIR "" CACHE PATH "Path to the stand-alone nvtx header")
|
||||
option(RABIT_MOCK "Build rabit with mock" OFF)
|
||||
option(HIDE_CXX_SYMBOLS "Build shared library and hide all C++ symbols" OFF)
|
||||
option(KEEP_BUILD_ARTIFACTS_IN_BINARY_DIR "Output build artifacts in CMake binary dir" OFF)
|
||||
## CUDA
|
||||
option(USE_CUDA "Build with GPU acceleration" OFF)
|
||||
option(USE_NCCL "Build with NCCL to enable distributed GPU support." OFF)
|
||||
option(BUILD_WITH_SHARED_NCCL "Build with shared NCCL library." OFF)
|
||||
option(BUILD_WITH_CUDA_CUB "Build with cub in CUDA installation" OFF)
|
||||
set(GPU_COMPUTE_VER "" CACHE STRING
|
||||
"Semicolon separated list of compute versions to be built against, e.g. '35;61'")
|
||||
## Copied From dmlc
|
||||
@@ -67,7 +65,6 @@ address, leak, undefined and thread.")
|
||||
## Plugins
|
||||
option(PLUGIN_DENSE_PARSER "Build dense parser plugin" OFF)
|
||||
option(PLUGIN_RMM "Build with RAPIDS Memory Manager (RMM)" OFF)
|
||||
option(PLUGIN_FEDERATED "Build with Federated Learning" OFF)
|
||||
## TODO: 1. Add check if DPC++ compiler is used for building
|
||||
option(PLUGIN_UPDATER_ONEAPI "DPC++ updater" OFF)
|
||||
option(ADD_PKGCONFIG "Add xgboost.pc into system." ON)
|
||||
@@ -115,20 +112,9 @@ endif (ENABLE_ALL_WARNINGS)
|
||||
if (BUILD_STATIC_LIB AND (R_LIB OR JVM_BINDINGS))
|
||||
message(SEND_ERROR "Cannot build a static library libxgboost.a when R or JVM packages are enabled.")
|
||||
endif (BUILD_STATIC_LIB AND (R_LIB OR JVM_BINDINGS))
|
||||
if (PLUGIN_FEDERATED)
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
message(SEND_ERROR "Cannot cross compile with federated learning support")
|
||||
endif ()
|
||||
if (BUILD_STATIC_LIB)
|
||||
message(SEND_ERROR "Cannot build static lib with federated learning support")
|
||||
endif ()
|
||||
if (R_LIB OR JVM_BINDINGS)
|
||||
message(SEND_ERROR "Cannot enable federated learning support when R or JVM packages are enabled.")
|
||||
endif ()
|
||||
if (WIN32)
|
||||
message(SEND_ERROR "Federated learning not supported for Windows platform")
|
||||
endif ()
|
||||
endif ()
|
||||
if (PLUGIN_RMM AND (NOT BUILD_WITH_CUDA_CUB))
|
||||
message(SEND_ERROR "Cannot build with RMM using cub submodule.")
|
||||
endif (PLUGIN_RMM AND (NOT BUILD_WITH_CUDA_CUB))
|
||||
|
||||
#-- Sanitizer
|
||||
if (USE_SANITIZER)
|
||||
@@ -143,14 +129,12 @@ if (USE_CUDA)
|
||||
message(STATUS "Configured CUDA host compiler: ${CMAKE_CUDA_HOST_COMPILER}")
|
||||
|
||||
enable_language(CUDA)
|
||||
if (${CMAKE_CUDA_COMPILER_VERSION} VERSION_LESS 11.0)
|
||||
message(FATAL_ERROR "CUDA version must be at least 11.0!")
|
||||
if (${CMAKE_CUDA_COMPILER_VERSION} VERSION_LESS 10.1)
|
||||
message(FATAL_ERROR "CUDA version must be at least 10.1!")
|
||||
endif()
|
||||
set(GEN_CODE "")
|
||||
format_gencode_flags("${GPU_COMPUTE_VER}" GEN_CODE)
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/gputreeshap)
|
||||
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
endif (USE_CUDA)
|
||||
|
||||
if (FORCE_COLORED_OUTPUT AND (CMAKE_GENERATOR STREQUAL "Ninja") AND
|
||||
@@ -163,30 +147,12 @@ find_package(Threads REQUIRED)
|
||||
|
||||
if (USE_OPENMP)
|
||||
if (APPLE)
|
||||
find_package(OpenMP)
|
||||
if (NOT OpenMP_FOUND)
|
||||
# Try again with extra path info; required for libomp 15+ from Homebrew
|
||||
execute_process(COMMAND brew --prefix libomp
|
||||
OUTPUT_VARIABLE HOMEBREW_LIBOMP_PREFIX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(OpenMP_C_FLAGS
|
||||
"-Xpreprocessor -fopenmp -I${HOMEBREW_LIBOMP_PREFIX}/include")
|
||||
set(OpenMP_CXX_FLAGS
|
||||
"-Xpreprocessor -fopenmp -I${HOMEBREW_LIBOMP_PREFIX}/include")
|
||||
set(OpenMP_C_LIB_NAMES omp)
|
||||
set(OpenMP_CXX_LIB_NAMES omp)
|
||||
set(OpenMP_omp_LIBRARY ${HOMEBREW_LIBOMP_PREFIX}/lib/libomp.dylib)
|
||||
find_package(OpenMP REQUIRED)
|
||||
endif ()
|
||||
else ()
|
||||
find_package(OpenMP REQUIRED)
|
||||
endif ()
|
||||
# Require CMake 3.16+ on Mac OSX, as previous versions of CMake had trouble locating
|
||||
# OpenMP on Mac. See https://github.com/dmlc/xgboost/pull/5146#issuecomment-568312706
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
endif (APPLE)
|
||||
find_package(OpenMP REQUIRED)
|
||||
endif (USE_OPENMP)
|
||||
#Add for IBM i
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "OS400")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> -X64 qc <TARGET> <OBJECTS>")
|
||||
endif()
|
||||
|
||||
if (USE_NCCL)
|
||||
find_package(Nccl REQUIRED)
|
||||
@@ -194,9 +160,6 @@ endif (USE_NCCL)
|
||||
|
||||
# dmlc-core
|
||||
msvc_use_static_runtime()
|
||||
if (FORCE_SHARED_CRT)
|
||||
set(DMLC_FORCE_SHARED_CRT ON)
|
||||
endif ()
|
||||
add_subdirectory(${xgboost_SOURCE_DIR}/dmlc-core)
|
||||
|
||||
if (MSVC)
|
||||
@@ -229,10 +192,6 @@ endif (JVM_BINDINGS)
|
||||
# Plugin
|
||||
add_subdirectory(${xgboost_SOURCE_DIR}/plugin)
|
||||
|
||||
if (PLUGIN_RMM)
|
||||
find_package(rmm REQUIRED)
|
||||
endif (PLUGIN_RMM)
|
||||
|
||||
#-- library
|
||||
if (BUILD_STATIC_LIB)
|
||||
add_library(xgboost STATIC)
|
||||
@@ -271,13 +230,8 @@ if (JVM_BINDINGS)
|
||||
xgboost_target_defs(xgboost4j)
|
||||
endif (JVM_BINDINGS)
|
||||
|
||||
if (KEEP_BUILD_ARTIFACTS_IN_BINARY_DIR)
|
||||
set_output_directory(runxgboost ${xgboost_BINARY_DIR})
|
||||
set_output_directory(xgboost ${xgboost_BINARY_DIR}/lib)
|
||||
else ()
|
||||
set_output_directory(runxgboost ${xgboost_SOURCE_DIR})
|
||||
set_output_directory(xgboost ${xgboost_SOURCE_DIR}/lib)
|
||||
endif ()
|
||||
set_output_directory(runxgboost ${xgboost_SOURCE_DIR})
|
||||
set_output_directory(xgboost ${xgboost_SOURCE_DIR}/lib)
|
||||
# Ensure these two targets do not build simultaneously, as they produce outputs with conflicting names
|
||||
add_dependencies(xgboost runxgboost)
|
||||
|
||||
@@ -342,7 +296,7 @@ write_basic_package_version_file(
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/xgboost-config.cmake
|
||||
${CMAKE_BINARY_DIR}/cmake/xgboost-config.cmake
|
||||
${CMAKE_BINARY_DIR}/cmake/xgboost-config-version.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xgboost)
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ The Project Management Committee(PMC) consists group of active committers that m
|
||||
- Tianqi is a Ph.D. student working on large-scale machine learning. He is the creator of the project.
|
||||
* [Michael Benesty](https://github.com/pommedeterresautee)
|
||||
- Michael is a lawyer and data scientist in France. He is the creator of XGBoost interactive analysis module in R.
|
||||
* [Yuan Tang](https://github.com/terrytangyuan), Akuity
|
||||
- Yuan is a founding engineer at Akuity. He contributed mostly in R and Python packages.
|
||||
* [Yuan Tang](https://github.com/terrytangyuan), Ant Group
|
||||
- Yuan is a software engineer in Ant Group. He contributed mostly in R and Python packages.
|
||||
* [Nan Zhu](https://github.com/CodingCat), Uber
|
||||
- Nan is a software engineer in Uber. He contributed mostly in JVM packages.
|
||||
* [Jiaming Yuan](https://github.com/trivialfis)
|
||||
|
||||
453
Jenkinsfile
vendored
Normal file
453
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,453 @@
|
||||
#!/usr/bin/groovy
|
||||
// -*- mode: groovy -*-
|
||||
// Jenkins pipeline
|
||||
// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
|
||||
|
||||
// Command to run command inside a docker container
|
||||
dockerRun = 'tests/ci_build/ci_build.sh'
|
||||
|
||||
// Which CUDA version to use when building reference distribution wheel
|
||||
ref_cuda_ver = '10.1'
|
||||
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field
|
||||
def commit_id // necessary to pass a variable from one stage to another
|
||||
|
||||
pipeline {
|
||||
// Each stage specify its own agent
|
||||
agent none
|
||||
|
||||
environment {
|
||||
DOCKER_CACHE_ECR_ID = '492475357299'
|
||||
DOCKER_CACHE_ECR_REGION = 'us-west-2'
|
||||
}
|
||||
|
||||
// Setup common job properties
|
||||
options {
|
||||
ansiColor('xterm')
|
||||
timestamps()
|
||||
timeout(time: 240, unit: 'MINUTES')
|
||||
buildDiscarder(logRotator(numToKeepStr: '10'))
|
||||
preserveStashes()
|
||||
}
|
||||
|
||||
// Build stages
|
||||
stages {
|
||||
stage('Jenkins Linux: Initialize') {
|
||||
agent { label 'job_initializer' }
|
||||
steps {
|
||||
script {
|
||||
def buildNumber = env.BUILD_NUMBER as int
|
||||
if (buildNumber > 1) milestone(buildNumber - 1)
|
||||
milestone(buildNumber)
|
||||
|
||||
checkoutSrcs()
|
||||
commit_id = "${GIT_COMMIT}"
|
||||
}
|
||||
sh 'python3 tests/jenkins_get_approval.py'
|
||||
stash name: 'srcs'
|
||||
}
|
||||
}
|
||||
stage('Jenkins Linux: Build') {
|
||||
agent none
|
||||
steps {
|
||||
script {
|
||||
parallel ([
|
||||
'clang-tidy': { ClangTidy() },
|
||||
'build-cpu': { BuildCPU() },
|
||||
'build-cpu-arm64': { BuildCPUARM64() },
|
||||
'build-cpu-rabit-mock': { BuildCPUMock() },
|
||||
// Build reference, distribution-ready Python wheel with CUDA 10.1
|
||||
// using CentOS 7 image
|
||||
'build-gpu-cuda10.1': { BuildCUDA(cuda_version: '10.1') },
|
||||
// The build-gpu-* builds below use Ubuntu image
|
||||
'build-gpu-cuda11.0': { BuildCUDA(cuda_version: '11.0', build_rmm: true) },
|
||||
'build-gpu-rpkg': { BuildRPackageWithCUDA(cuda_version: '10.1') },
|
||||
'build-jvm-packages-gpu-cuda10.1': { BuildJVMPackagesWithCUDA(spark_version: '3.0.0', cuda_version: '11.0') },
|
||||
'build-jvm-packages': { BuildJVMPackages(spark_version: '3.0.0') },
|
||||
'build-jvm-doc': { BuildJVMDoc() }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Jenkins Linux: Test') {
|
||||
agent none
|
||||
steps {
|
||||
script {
|
||||
parallel ([
|
||||
'test-python-cpu': { TestPythonCPU() },
|
||||
'test-python-cpu-arm64': { TestPythonCPUARM64() },
|
||||
// artifact_cuda_version doesn't apply to RMM tests; RMM tests will always match CUDA version between artifact and host env
|
||||
'test-python-gpu-cuda11.0-cross': { TestPythonGPU(artifact_cuda_version: '10.1', host_cuda_version: '11.0', test_rmm: true) },
|
||||
'test-python-gpu-cuda11.0': { TestPythonGPU(artifact_cuda_version: '11.0', host_cuda_version: '11.0') },
|
||||
'test-python-mgpu-cuda11.0': { TestPythonGPU(artifact_cuda_version: '10.1', host_cuda_version: '11.0', multi_gpu: true, test_rmm: true) },
|
||||
'test-cpp-gpu-cuda11.0': { TestCppGPU(artifact_cuda_version: '11.0', host_cuda_version: '11.0', test_rmm: true) },
|
||||
'test-jvm-jdk8': { CrossTestJVMwithJDK(jdk_version: '8', spark_version: '3.0.0') },
|
||||
'test-jvm-jdk11': { CrossTestJVMwithJDK(jdk_version: '11') },
|
||||
'test-jvm-jdk12': { CrossTestJVMwithJDK(jdk_version: '12') }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Jenkins Linux: Deploy') {
|
||||
agent none
|
||||
steps {
|
||||
script {
|
||||
parallel ([
|
||||
'deploy-jvm-packages': { DeployJVMPackages(spark_version: '3.0.0') }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check out source code from git
|
||||
def checkoutSrcs() {
|
||||
retry(5) {
|
||||
try {
|
||||
timeout(time: 2, unit: 'MINUTES') {
|
||||
checkout scm
|
||||
sh 'git submodule update --init'
|
||||
}
|
||||
} catch (exc) {
|
||||
deleteDir()
|
||||
error "Failed to fetch source codes"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def GetCUDABuildContainerType(cuda_version) {
|
||||
return (cuda_version == ref_cuda_ver) ? 'gpu_build_centos7' : 'gpu_build'
|
||||
}
|
||||
|
||||
def ClangTidy() {
|
||||
node('linux && cpu_build') {
|
||||
unstash name: 'srcs'
|
||||
echo "Running clang-tidy job..."
|
||||
def container_type = "clang_tidy"
|
||||
def docker_binary = "docker"
|
||||
def dockerArgs = "--build-arg CUDA_VERSION_ARG=10.1"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${dockerArgs} python3 tests/ci_build/tidy.py
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildCPU() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build CPU"
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} rm -fv dmlc-core/include/dmlc/build_config_default.h
|
||||
# This step is not necessary, but here we include it, to ensure that DMLC_CORE_USE_CMAKE flag is correctly propagated
|
||||
# We want to make sure that we use the configured header build/dmlc/build_config.h instead of include/dmlc/build_config_default.h.
|
||||
# See discussion at https://github.com/dmlc/xgboost/issues/5510
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_via_cmake.sh -DPLUGIN_DENSE_PARSER=ON
|
||||
${dockerRun} ${container_type} ${docker_binary} bash -c "cd build && ctest --extra-verbose"
|
||||
"""
|
||||
// Sanitizer test
|
||||
def docker_extra_params = "CI_DOCKER_EXTRA_PARAMS_INIT='-e ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer -e ASAN_OPTIONS=symbolize=1 -e UBSAN_OPTIONS=print_stacktrace=1:log_path=ubsan_error.log --cap-add SYS_PTRACE'"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_via_cmake.sh -DUSE_SANITIZER=ON -DENABLED_SANITIZERS="address;leak;undefined" \
|
||||
-DCMAKE_BUILD_TYPE=Debug -DSANITIZER_PATH=/usr/lib/x86_64-linux-gnu/
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} bash -c "cd build && ctest --exclude-regex AllTestsInDMLCUnitTests --extra-verbose"
|
||||
"""
|
||||
|
||||
stash name: 'xgboost_cli', includes: 'xgboost'
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildCPUARM64() {
|
||||
node('linux && arm64') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build CPU ARM64"
|
||||
def container_type = "aarch64"
|
||||
def docker_binary = "docker"
|
||||
def wheel_tag = "manylinux2014_aarch64"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_via_cmake.sh --conda-env=aarch64_test -DOPEN_MP:BOOL=ON -DHIDE_CXX_SYMBOL=ON
|
||||
${dockerRun} ${container_type} ${docker_binary} bash -c "cd build && ctest --extra-verbose"
|
||||
${dockerRun} ${container_type} ${docker_binary} bash -c "cd python-package && rm -rf dist/* && python setup.py bdist_wheel --universal"
|
||||
${dockerRun} ${container_type} ${docker_binary} python tests/ci_build/rename_whl.py python-package/dist/*.whl ${commit_id} ${wheel_tag}
|
||||
${dockerRun} ${container_type} ${docker_binary} bash -c "auditwheel repair --plat ${wheel_tag} python-package/dist/*.whl && python tests/ci_build/rename_whl.py wheelhouse/*.whl ${commit_id} ${wheel_tag}"
|
||||
mv -v wheelhouse/*.whl python-package/dist/
|
||||
# Make sure that libgomp.so is vendored in the wheel
|
||||
${dockerRun} ${container_type} ${docker_binary} bash -c "unzip -l python-package/dist/*.whl | grep libgomp || exit -1"
|
||||
"""
|
||||
echo 'Stashing Python wheel...'
|
||||
stash name: "xgboost_whl_arm64_cpu", includes: 'python-package/dist/*.whl'
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
echo 'Uploading Python wheel...'
|
||||
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
|
||||
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', workingDir: 'python-package/dist', includePathPattern:'**/*.whl'
|
||||
}
|
||||
stash name: 'xgboost_cli_arm64', includes: 'xgboost'
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildCPUMock() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build CPU with rabit mock"
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_mock_cmake.sh
|
||||
"""
|
||||
echo 'Stashing rabit C++ test executable (xgboost)...'
|
||||
stash name: 'xgboost_rabit_tests', includes: 'xgboost'
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildCUDA(args) {
|
||||
node('linux && cpu_build') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build with CUDA ${args.cuda_version}"
|
||||
def container_type = GetCUDABuildContainerType(args.cuda_version)
|
||||
def docker_binary = "docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.cuda_version}"
|
||||
def arch_flag = ""
|
||||
if (env.BRANCH_NAME != 'master' && !(env.BRANCH_NAME.startsWith('release'))) {
|
||||
arch_flag = "-DGPU_COMPUTE_VER=75"
|
||||
}
|
||||
def wheel_tag = "manylinux2014_x86_64"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_via_cmake.sh -DUSE_CUDA=ON -DUSE_NCCL=ON -DOPEN_MP:BOOL=ON -DHIDE_CXX_SYMBOLS=ON ${arch_flag}
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} bash -c "cd python-package && rm -rf dist/* && python setup.py bdist_wheel --universal"
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} python tests/ci_build/rename_whl.py python-package/dist/*.whl ${commit_id} ${wheel_tag}
|
||||
"""
|
||||
if (args.cuda_version == ref_cuda_ver) {
|
||||
sh """
|
||||
${dockerRun} auditwheel_x86_64 ${docker_binary} auditwheel repair --plat ${wheel_tag} python-package/dist/*.whl
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} python tests/ci_build/rename_whl.py wheelhouse/*.whl ${commit_id} ${wheel_tag}
|
||||
mv -v wheelhouse/*.whl python-package/dist/
|
||||
# Make sure that libgomp.so is vendored in the wheel
|
||||
${dockerRun} auditwheel_x86_64 ${docker_binary} bash -c "unzip -l python-package/dist/*.whl | grep libgomp || exit -1"
|
||||
"""
|
||||
}
|
||||
echo 'Stashing Python wheel...'
|
||||
stash name: "xgboost_whl_cuda${args.cuda_version}", includes: 'python-package/dist/*.whl'
|
||||
if (args.cuda_version == ref_cuda_ver && (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release'))) {
|
||||
echo 'Uploading Python wheel...'
|
||||
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
|
||||
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', workingDir: 'python-package/dist', includePathPattern:'**/*.whl'
|
||||
}
|
||||
echo 'Stashing C++ test executable (testxgboost)...'
|
||||
stash name: "xgboost_cpp_tests_cuda${args.cuda_version}", includes: 'build/testxgboost'
|
||||
if (args.build_rmm) {
|
||||
echo "Build with CUDA ${args.cuda_version} and RMM"
|
||||
container_type = "rmm"
|
||||
docker_binary = "docker"
|
||||
docker_args = "--build-arg CUDA_VERSION_ARG=${args.cuda_version}"
|
||||
sh """
|
||||
rm -rf build/
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_via_cmake.sh --conda-env=gpu_test -DUSE_CUDA=ON -DUSE_NCCL=ON -DPLUGIN_RMM=ON -DBUILD_WITH_CUDA_CUB=ON ${arch_flag}
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} bash -c "cd python-package && rm -rf dist/* && python setup.py bdist_wheel --universal"
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} python tests/ci_build/rename_whl.py python-package/dist/*.whl ${commit_id} manylinux2014_x86_64
|
||||
"""
|
||||
echo 'Stashing Python wheel...'
|
||||
stash name: "xgboost_whl_rmm_cuda${args.cuda_version}", includes: 'python-package/dist/*.whl'
|
||||
echo 'Stashing C++ test executable (testxgboost)...'
|
||||
stash name: "xgboost_cpp_tests_rmm_cuda${args.cuda_version}", includes: 'build/testxgboost'
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildRPackageWithCUDA(args) {
|
||||
node('linux && cpu_build') {
|
||||
unstash name: 'srcs'
|
||||
def container_type = 'gpu_build_r_centos7'
|
||||
def docker_binary = "docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.cuda_version}"
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_r_pkg_with_cuda.sh ${commit_id}
|
||||
"""
|
||||
echo 'Uploading R tarball...'
|
||||
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
|
||||
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', includePathPattern:'xgboost_r_gpu_linux_*.tar.gz'
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildJVMPackagesWithCUDA(args) {
|
||||
node('linux && mgpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build XGBoost4J-Spark with Spark ${args.spark_version}, CUDA ${args.cuda_version}"
|
||||
def container_type = "jvm_gpu_build"
|
||||
def docker_binary = "nvidia-docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.cuda_version}"
|
||||
def arch_flag = ""
|
||||
if (env.BRANCH_NAME != 'master' && !(env.BRANCH_NAME.startsWith('release'))) {
|
||||
arch_flag = "-DGPU_COMPUTE_VER=75"
|
||||
}
|
||||
// Use only 4 CPU cores
|
||||
def docker_extra_params = "CI_DOCKER_EXTRA_PARAMS_INIT='--cpuset-cpus 0-3'"
|
||||
sh """
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_jvm_packages.sh ${args.spark_version} -Duse.cuda=ON $arch_flag
|
||||
"""
|
||||
echo "Stashing XGBoost4J JAR with CUDA ${args.cuda_version} ..."
|
||||
stash name: 'xgboost4j_jar_gpu', includes: "jvm-packages/xgboost4j-gpu/target/*.jar,jvm-packages/xgboost4j-spark-gpu/target/*.jar"
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildJVMPackages(args) {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Build XGBoost4J-Spark with Spark ${args.spark_version}"
|
||||
def container_type = "jvm"
|
||||
def docker_binary = "docker"
|
||||
// Use only 4 CPU cores
|
||||
def docker_extra_params = "CI_DOCKER_EXTRA_PARAMS_INIT='--cpuset-cpus 0-3'"
|
||||
sh """
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_jvm_packages.sh ${args.spark_version}
|
||||
"""
|
||||
echo 'Stashing XGBoost4J JAR...'
|
||||
stash name: 'xgboost4j_jar', includes: "jvm-packages/xgboost4j/target/*.jar,jvm-packages/xgboost4j-spark/target/*.jar,jvm-packages/xgboost4j-example/target/*.jar"
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildJVMDoc() {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
echo "Building JVM doc..."
|
||||
def container_type = "jvm"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_jvm_doc.sh ${BRANCH_NAME}
|
||||
"""
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
echo 'Uploading doc...'
|
||||
s3Upload file: "jvm-packages/${BRANCH_NAME}.tar.bz2", bucket: 'xgboost-docs', acl: 'PublicRead', path: "${BRANCH_NAME}.tar.bz2"
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def TestPythonCPU() {
|
||||
node('linux && cpu') {
|
||||
unstash name: "xgboost_whl_cuda${ref_cuda_ver}"
|
||||
unstash name: 'srcs'
|
||||
unstash name: 'xgboost_cli'
|
||||
echo "Test Python CPU"
|
||||
def container_type = "cpu"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/test_python.sh cpu
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def TestPythonCPUARM64() {
|
||||
node('linux && arm64') {
|
||||
unstash name: "xgboost_whl_arm64_cpu"
|
||||
unstash name: 'srcs'
|
||||
unstash name: 'xgboost_cli_arm64'
|
||||
echo "Test Python CPU ARM64"
|
||||
def container_type = "aarch64"
|
||||
def docker_binary = "docker"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/test_python.sh cpu-arm64
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def TestPythonGPU(args) {
|
||||
def nodeReq = (args.multi_gpu) ? 'linux && mgpu' : 'linux && gpu'
|
||||
def artifact_cuda_version = (args.artifact_cuda_version) ?: ref_cuda_ver
|
||||
node(nodeReq) {
|
||||
unstash name: "xgboost_whl_cuda${artifact_cuda_version}"
|
||||
unstash name: "xgboost_cpp_tests_cuda${artifact_cuda_version}"
|
||||
unstash name: 'srcs'
|
||||
echo "Test Python GPU: CUDA ${args.host_cuda_version}"
|
||||
def container_type = "gpu"
|
||||
def docker_binary = "nvidia-docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.host_cuda_version}"
|
||||
def mgpu_indicator = (args.multi_gpu) ? 'mgpu' : 'gpu'
|
||||
// Allocate extra space in /dev/shm to enable NCCL
|
||||
def docker_extra_params = (args.multi_gpu) ? "CI_DOCKER_EXTRA_PARAMS_INIT='--shm-size=4g'" : ''
|
||||
sh "${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_python.sh ${mgpu_indicator}"
|
||||
if (args.test_rmm) {
|
||||
sh "rm -rfv build/ python-package/dist/"
|
||||
unstash name: "xgboost_whl_rmm_cuda${args.host_cuda_version}"
|
||||
unstash name: "xgboost_cpp_tests_rmm_cuda${args.host_cuda_version}"
|
||||
sh "${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_python.sh ${mgpu_indicator} --use-rmm-pool"
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def TestCppGPU(args) {
|
||||
def nodeReq = 'linux && mgpu'
|
||||
def artifact_cuda_version = (args.artifact_cuda_version) ?: ref_cuda_ver
|
||||
node(nodeReq) {
|
||||
unstash name: "xgboost_cpp_tests_cuda${artifact_cuda_version}"
|
||||
unstash name: 'srcs'
|
||||
echo "Test C++, CUDA ${args.host_cuda_version}"
|
||||
def container_type = "gpu"
|
||||
def docker_binary = "nvidia-docker"
|
||||
def docker_args = "--build-arg CUDA_VERSION_ARG=${args.host_cuda_version}"
|
||||
sh "${dockerRun} ${container_type} ${docker_binary} ${docker_args} build/testxgboost"
|
||||
if (args.test_rmm) {
|
||||
sh "rm -rfv build/"
|
||||
unstash name: "xgboost_cpp_tests_rmm_cuda${args.host_cuda_version}"
|
||||
echo "Test C++, CUDA ${args.host_cuda_version} with RMM"
|
||||
container_type = "rmm"
|
||||
docker_binary = "nvidia-docker"
|
||||
docker_args = "--build-arg CUDA_VERSION_ARG=${args.host_cuda_version}"
|
||||
sh """
|
||||
${dockerRun} ${container_type} ${docker_binary} ${docker_args} bash -c "source activate gpu_test && build/testxgboost --use-rmm-pool --gtest_filter=-*DeathTest.*"
|
||||
"""
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def CrossTestJVMwithJDK(args) {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'xgboost4j_jar'
|
||||
unstash name: 'srcs'
|
||||
if (args.spark_version != null) {
|
||||
echo "Test XGBoost4J on a machine with JDK ${args.jdk_version}, Spark ${args.spark_version}"
|
||||
} else {
|
||||
echo "Test XGBoost4J on a machine with JDK ${args.jdk_version}"
|
||||
}
|
||||
def container_type = "jvm_cross"
|
||||
def docker_binary = "docker"
|
||||
def spark_arg = (args.spark_version != null) ? "--build-arg SPARK_VERSION=${args.spark_version}" : ""
|
||||
def docker_args = "--build-arg JDK_VERSION=${args.jdk_version} ${spark_arg}"
|
||||
// Run integration tests only when spark_version is given
|
||||
def docker_extra_params = (args.spark_version != null) ? "CI_DOCKER_EXTRA_PARAMS_INIT='-e RUN_INTEGRATION_TEST=1'" : ""
|
||||
sh """
|
||||
${docker_extra_params} ${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/test_jvm_cross.sh
|
||||
"""
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def DeployJVMPackages(args) {
|
||||
node('linux && cpu') {
|
||||
unstash name: 'srcs'
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
echo 'Deploying to xgboost-maven-repo S3 repo...'
|
||||
sh """
|
||||
${dockerRun} jvm_gpu_build docker --build-arg CUDA_VERSION_ARG=10.1 tests/ci_build/deploy_jvm_packages.sh ${args.spark_version}
|
||||
"""
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
163
Jenkinsfile-win64
Normal file
163
Jenkinsfile-win64
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/groovy
|
||||
// -*- mode: groovy -*-
|
||||
|
||||
/* Jenkins pipeline for Windows AMD64 target */
|
||||
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field
|
||||
def commit_id // necessary to pass a variable from one stage to another
|
||||
|
||||
pipeline {
|
||||
agent none
|
||||
|
||||
// Setup common job properties
|
||||
options {
|
||||
timestamps()
|
||||
timeout(time: 240, unit: 'MINUTES')
|
||||
buildDiscarder(logRotator(numToKeepStr: '10'))
|
||||
preserveStashes()
|
||||
}
|
||||
|
||||
// Build stages
|
||||
stages {
|
||||
stage('Jenkins Win64: Initialize') {
|
||||
agent { label 'job_initializer' }
|
||||
steps {
|
||||
script {
|
||||
def buildNumber = env.BUILD_NUMBER as int
|
||||
if (buildNumber > 1) milestone(buildNumber - 1)
|
||||
milestone(buildNumber)
|
||||
checkoutSrcs()
|
||||
commit_id = "${GIT_COMMIT}"
|
||||
}
|
||||
sh 'python3 tests/jenkins_get_approval.py'
|
||||
stash name: 'srcs'
|
||||
}
|
||||
}
|
||||
stage('Jenkins Win64: Build') {
|
||||
agent none
|
||||
steps {
|
||||
script {
|
||||
parallel ([
|
||||
'build-win64-cuda10.1': { BuildWin64() },
|
||||
'build-rpkg-win64-cuda10.1': { BuildRPackageWithCUDAWin64() }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Jenkins Win64: Test') {
|
||||
agent none
|
||||
steps {
|
||||
script {
|
||||
parallel ([
|
||||
'test-win64-cuda10.1': { TestWin64() },
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check out source code from git
|
||||
def checkoutSrcs() {
|
||||
retry(5) {
|
||||
try {
|
||||
timeout(time: 2, unit: 'MINUTES') {
|
||||
checkout scm
|
||||
sh 'git submodule update --init'
|
||||
}
|
||||
} catch (exc) {
|
||||
deleteDir()
|
||||
error "Failed to fetch source codes"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def BuildWin64() {
|
||||
node('win64 && cuda10_unified') {
|
||||
deleteDir()
|
||||
unstash name: 'srcs'
|
||||
echo "Building XGBoost for Windows AMD64 target..."
|
||||
bat "nvcc --version"
|
||||
def arch_flag = ""
|
||||
if (env.BRANCH_NAME != 'master' && !(env.BRANCH_NAME.startsWith('release'))) {
|
||||
arch_flag = "-DGPU_COMPUTE_VER=75"
|
||||
}
|
||||
bat """
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G"Visual Studio 15 2017 Win64" -DUSE_CUDA=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON ${arch_flag} -DCMAKE_UNITY_BUILD=ON
|
||||
"""
|
||||
bat """
|
||||
cd build
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\MSBuild\\15.0\\Bin\\MSBuild.exe" xgboost.sln /m /p:Configuration=Release /nodeReuse:false
|
||||
"""
|
||||
bat """
|
||||
cd python-package
|
||||
conda activate && python setup.py bdist_wheel --universal && for /R %%i in (dist\\*.whl) DO python ../tests/ci_build/rename_whl.py "%%i" ${commit_id} win_amd64
|
||||
"""
|
||||
echo "Insert vcomp140.dll (OpenMP runtime) into the wheel..."
|
||||
bat """
|
||||
cd python-package\\dist
|
||||
COPY /B ..\\..\\tests\\ci_build\\insert_vcomp140.py
|
||||
conda activate && python insert_vcomp140.py *.whl
|
||||
"""
|
||||
echo 'Stashing Python wheel...'
|
||||
stash name: 'xgboost_whl', includes: 'python-package/dist/*.whl'
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
echo 'Uploading Python wheel...'
|
||||
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
|
||||
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', workingDir: 'python-package/dist', includePathPattern:'**/*.whl'
|
||||
}
|
||||
echo 'Stashing C++ test executable (testxgboost)...'
|
||||
stash name: 'xgboost_cpp_tests', includes: 'build/testxgboost.exe'
|
||||
stash name: 'xgboost_cli', includes: 'xgboost.exe'
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def BuildRPackageWithCUDAWin64() {
|
||||
node('win64 && cuda10_unified') {
|
||||
deleteDir()
|
||||
unstash name: 'srcs'
|
||||
bat "nvcc --version"
|
||||
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
|
||||
bat """
|
||||
bash tests/ci_build/build_r_pkg_with_cuda_win64.sh ${commit_id}
|
||||
"""
|
||||
echo 'Uploading R tarball...'
|
||||
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
|
||||
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', includePathPattern:'xgboost_r_gpu_win64_*.tar.gz'
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
|
||||
def TestWin64() {
|
||||
node('win64 && cuda10_unified') {
|
||||
deleteDir()
|
||||
unstash name: 'srcs'
|
||||
unstash name: 'xgboost_whl'
|
||||
unstash name: 'xgboost_cli'
|
||||
unstash name: 'xgboost_cpp_tests'
|
||||
echo "Test Win64"
|
||||
bat "nvcc --version"
|
||||
echo "Running C++ tests..."
|
||||
bat "build\\testxgboost.exe"
|
||||
echo "Installing Python dependencies..."
|
||||
def env_name = 'win64_' + UUID.randomUUID().toString().replaceAll('-', '')
|
||||
bat "conda activate && mamba env create -n ${env_name} --file=tests/ci_build/conda_env/win64_test.yml"
|
||||
echo "Installing Python wheel..."
|
||||
bat """
|
||||
conda activate ${env_name} && for /R %%i in (python-package\\dist\\*.whl) DO python -m pip install "%%i"
|
||||
"""
|
||||
echo "Running Python tests..."
|
||||
bat "conda activate ${env_name} && python -m pytest -v -s -rxXs --fulltrace tests\\python"
|
||||
bat """
|
||||
conda activate ${env_name} && python -m pytest -v -s -rxXs --fulltrace -m "(not slow) and (not mgpu)" tests\\python-gpu
|
||||
"""
|
||||
bat "conda env remove --name ${env_name}"
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
165
Makefile
Normal file
165
Makefile
Normal file
@@ -0,0 +1,165 @@
|
||||
ifndef DMLC_CORE
|
||||
DMLC_CORE = dmlc-core
|
||||
endif
|
||||
|
||||
ifndef RABIT
|
||||
RABIT = rabit
|
||||
endif
|
||||
|
||||
ROOTDIR = $(CURDIR)
|
||||
|
||||
# workarounds for some buggy old make & msys2 versions seen in windows
|
||||
ifeq (NA, $(shell test ! -d "$(ROOTDIR)" && echo NA ))
|
||||
$(warning Attempting to fix non-existing ROOTDIR [$(ROOTDIR)])
|
||||
ROOTDIR := $(shell pwd)
|
||||
$(warning New ROOTDIR [$(ROOTDIR)] $(shell test -d "$(ROOTDIR)" && echo " is OK" ))
|
||||
endif
|
||||
MAKE_OK := $(shell "$(MAKE)" -v 2> /dev/null)
|
||||
ifndef MAKE_OK
|
||||
$(warning Attempting to recover non-functional MAKE [$(MAKE)])
|
||||
MAKE := $(shell which make 2> /dev/null)
|
||||
MAKE_OK := $(shell "$(MAKE)" -v 2> /dev/null)
|
||||
endif
|
||||
$(warning MAKE [$(MAKE)] - $(if $(MAKE_OK),checked OK,PROBLEM))
|
||||
|
||||
include $(DMLC_CORE)/make/dmlc.mk
|
||||
|
||||
# set compiler defaults for OSX versus *nix
|
||||
# let people override either
|
||||
OS := $(shell uname)
|
||||
ifeq ($(OS), Darwin)
|
||||
ifndef CC
|
||||
export CC = $(if $(shell which clang), clang, gcc)
|
||||
endif
|
||||
ifndef CXX
|
||||
export CXX = $(if $(shell which clang++), clang++, g++)
|
||||
endif
|
||||
else
|
||||
# linux defaults
|
||||
ifndef CC
|
||||
export CC = gcc
|
||||
endif
|
||||
ifndef CXX
|
||||
export CXX = g++
|
||||
endif
|
||||
endif
|
||||
|
||||
export CFLAGS= -DDMLC_LOG_CUSTOMIZE=1 -std=c++14 -Wall -Wno-unknown-pragmas -Iinclude $(ADD_CFLAGS)
|
||||
CFLAGS += -I$(DMLC_CORE)/include -I$(RABIT)/include -I$(GTEST_PATH)/include
|
||||
|
||||
ifeq ($(TEST_COVER), 1)
|
||||
CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage
|
||||
else
|
||||
CFLAGS += -O3 -funroll-loops
|
||||
endif
|
||||
|
||||
ifndef LINT_LANG
|
||||
LINT_LANG= "all"
|
||||
endif
|
||||
|
||||
# specify tensor path
|
||||
.PHONY: clean all lint clean_all doxygen rcpplint pypack Rpack Rbuild Rcheck
|
||||
|
||||
build/%.o: src/%.cc
|
||||
@mkdir -p $(@D)
|
||||
$(CXX) $(CFLAGS) -MM -MT build/$*.o $< >build/$*.d
|
||||
$(CXX) -c $(CFLAGS) $< -o $@
|
||||
|
||||
# The should be equivalent to $(ALL_OBJ) except for build/cli_main.o
|
||||
amalgamation/xgboost-all0.o: amalgamation/xgboost-all0.cc
|
||||
$(CXX) -c $(CFLAGS) $< -o $@
|
||||
|
||||
rcpplint:
|
||||
python3 dmlc-core/scripts/lint.py xgboost ${LINT_LANG} R-package/src
|
||||
|
||||
lint: rcpplint
|
||||
python3 dmlc-core/scripts/lint.py --exclude_path python-package/xgboost/dmlc-core \
|
||||
python-package/xgboost/include python-package/xgboost/lib \
|
||||
python-package/xgboost/make python-package/xgboost/rabit \
|
||||
python-package/xgboost/src --pylint-rc ${PWD}/python-package/.pylintrc xgboost \
|
||||
${LINT_LANG} include src python-package
|
||||
|
||||
ifeq ($(TEST_COVER), 1)
|
||||
cover: check
|
||||
@- $(foreach COV_OBJ, $(COVER_OBJ), \
|
||||
gcov -pbcul -o $(shell dirname $(COV_OBJ)) $(COV_OBJ) > gcov.log || cat gcov.log; \
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
# dask is required to pass, others are not
|
||||
# If any of the dask tests failed, contributor won't see the other error.
|
||||
mypy:
|
||||
cd python-package; \
|
||||
mypy ./xgboost/dask.py && \
|
||||
mypy ./xgboost/rabit.py && \
|
||||
mypy ../demo/guide-python/external_memory.py && \
|
||||
mypy ../tests/python-gpu/test_gpu_with_dask.py && \
|
||||
mypy ../tests/python/test_data_iterator.py && \
|
||||
mypy ../tests/python-gpu/test_gpu_data_iterator.py && \
|
||||
mypy ./xgboost/sklearn.py || exit 1; \
|
||||
mypy . || true ;
|
||||
|
||||
clean:
|
||||
$(RM) -rf build lib bin *~ */*~ */*/*~ */*/*/*~ */*.o */*/*.o */*/*/*.o #xgboost
|
||||
$(RM) -rf build_tests *.gcov tests/cpp/xgboost_test
|
||||
if [ -d "R-package/src" ]; then \
|
||||
cd R-package/src; \
|
||||
$(RM) -rf rabit src include dmlc-core amalgamation *.so *.dll; \
|
||||
cd $(ROOTDIR); \
|
||||
fi
|
||||
|
||||
clean_all: clean
|
||||
cd $(DMLC_CORE); "$(MAKE)" clean; cd $(ROOTDIR)
|
||||
cd $(RABIT); "$(MAKE)" clean; cd $(ROOTDIR)
|
||||
|
||||
# create pip source dist (sdist) pack for PyPI
|
||||
pippack: clean_all
|
||||
cd python-package; python setup.py sdist; mv dist/*.tar.gz ..; cd ..
|
||||
|
||||
# Script to make a clean installable R package.
|
||||
Rpack: clean_all
|
||||
rm -rf xgboost xgboost*.tar.gz
|
||||
cp -r R-package xgboost
|
||||
rm -rf xgboost/src/*.o xgboost/src/*.so xgboost/src/*.dll
|
||||
rm -rf xgboost/src/*/*.o
|
||||
rm -rf xgboost/demo/*.model xgboost/demo/*.buffer xgboost/demo/*.txt
|
||||
rm -rf xgboost/demo/runall.R
|
||||
cp -r src xgboost/src/src
|
||||
cp -r include xgboost/src/include
|
||||
cp -r amalgamation xgboost/src/amalgamation
|
||||
mkdir -p xgboost/src/rabit
|
||||
cp -r rabit/include xgboost/src/rabit/include
|
||||
cp -r rabit/src xgboost/src/rabit/src
|
||||
rm -rf xgboost/src/rabit/src/*.o
|
||||
mkdir -p xgboost/src/dmlc-core
|
||||
cp -r dmlc-core/include xgboost/src/dmlc-core/include
|
||||
cp -r dmlc-core/src xgboost/src/dmlc-core/src
|
||||
cp ./LICENSE xgboost
|
||||
# Modify PKGROOT in Makevars.in
|
||||
cat R-package/src/Makevars.in|sed '2s/.*/PKGROOT=./' > xgboost/src/Makevars.in
|
||||
# Configure Makevars.win (Windows-specific Makevars, likely using MinGW)
|
||||
cp xgboost/src/Makevars.in xgboost/src/Makevars.win
|
||||
cat xgboost/src/Makevars.in| sed '3s/.*/ENABLE_STD_THREAD=0/' > xgboost/src/Makevars.win
|
||||
sed -i -e 's/@OPENMP_CXXFLAGS@/$$\(SHLIB_OPENMP_CXXFLAGS\)/g' xgboost/src/Makevars.win
|
||||
sed -i -e 's/-pthread/$$\(SHLIB_PTHREAD_FLAGS\)/g' xgboost/src/Makevars.win
|
||||
sed -i -e 's/@ENDIAN_FLAG@/-DDMLC_CMAKE_LITTLE_ENDIAN=1/g' xgboost/src/Makevars.win
|
||||
sed -i -e 's/@BACKTRACE_LIB@//g' xgboost/src/Makevars.win
|
||||
sed -i -e 's/@OPENMP_LIB@//g' xgboost/src/Makevars.win
|
||||
rm -f xgboost/src/Makevars.win-e # OSX sed create this extra file; remove it
|
||||
bash R-package/remove_warning_suppression_pragma.sh
|
||||
bash xgboost/remove_warning_suppression_pragma.sh
|
||||
rm xgboost/remove_warning_suppression_pragma.sh
|
||||
rm -rfv xgboost/tests/helper_scripts/
|
||||
|
||||
R ?= R
|
||||
|
||||
Rbuild: Rpack
|
||||
$(R) CMD build xgboost
|
||||
rm -rf xgboost
|
||||
|
||||
Rcheck: Rbuild
|
||||
$(R) CMD check --as-cran xgboost*.tar.gz
|
||||
|
||||
-include build/*.d
|
||||
-include build/*/*.d
|
||||
712
NEWS.md
712
NEWS.md
@@ -3,718 +3,6 @@ XGBoost Change Log
|
||||
|
||||
This file records the changes in xgboost library in reverse chronological order.
|
||||
|
||||
## 1.7.6 (2023 Jun 16)
|
||||
|
||||
This is a patch release for bug fixes. The CRAN package for the R binding is kept at 1.7.5.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix distributed training with mixed dense and sparse partitions. (#9272)
|
||||
* Fix monotone constraints on CPU with large trees. (#9122)
|
||||
* [spark] Make the spark model have the same UID as its estimator (#9022)
|
||||
* Optimize prediction with `QuantileDMatrix`. (#9096)
|
||||
|
||||
### Document
|
||||
* Improve doxygen (#8959)
|
||||
* Update the cuDF pip index URL. (#9106)
|
||||
|
||||
### Maintenance
|
||||
* Fix tests with pandas 2.0. (#9014)
|
||||
|
||||
## 1.7.5 (2023 Mar 30)
|
||||
This is a patch release for bug fixes.
|
||||
|
||||
* C++ requirement is updated to C++-17, along with which, CUDA 11.8 is used as the default CTK. (#8860, #8855, #8853)
|
||||
* Fix import for pyspark ranker. (#8692)
|
||||
* Fix Windows binary wheel to be compatible with Poetry (#8991)
|
||||
* Fix GPU hist with column sampling. (#8850)
|
||||
* Make sure iterative DMatrix is properly initialized. (#8997)
|
||||
* [R] Update link in document. (#8998)
|
||||
|
||||
## 1.7.4 (2023 Feb 16)
|
||||
This is a patch release for bug fixes.
|
||||
|
||||
* [R] Fix OpenMP detection on macOS. (#8684)
|
||||
* [Python] Make sure input numpy array is aligned. (#8690)
|
||||
* Fix feature interaction with column sampling in gpu_hist evaluator. (#8754)
|
||||
* Fix GPU L1 error. (#8749)
|
||||
* [PySpark] Fix feature types param (#8772)
|
||||
* Fix ranking with quantile dmatrix and group weight. (#8762)
|
||||
|
||||
## 1.7.3 (2023 Jan 6)
|
||||
This is a patch release for bug fixes.
|
||||
|
||||
* [Breaking] XGBoost Sklearn estimator method `get_params` no longer returns internally configured values. (#8634)
|
||||
* Fix linalg iterator, which may crash the L1 error. (#8603)
|
||||
* Fix loading pickled GPU model with a CPU-only XGBoost build. (#8632)
|
||||
* Fix inference with unseen categories with categorical features. (#8591, #8602)
|
||||
* CI fixes. (#8620, #8631, #8579)
|
||||
|
||||
## v1.7.2 (2022 Dec 8)
|
||||
This is a patch release for bug fixes.
|
||||
|
||||
* Work with newer thrust and libcudacxx (#8432)
|
||||
* Support null value in CUDA array interface namespace. (#8486)
|
||||
* Use `getsockname` instead of `SO_DOMAIN` on AIX. (#8437)
|
||||
* [pyspark] Make QDM optional based on a cuDF check (#8471)
|
||||
* [pyspark] sort qid for SparkRanker. (#8497)
|
||||
* [dask] Properly await async method client.wait_for_workers. (#8558)
|
||||
|
||||
* [R] Fix CRAN test notes. (#8428)
|
||||
|
||||
* [doc] Fix outdated document [skip ci]. (#8527)
|
||||
* [CI] Fix github action mismatched glibcxx. (#8551)
|
||||
|
||||
## v1.7.1 (2022 Nov 3)
|
||||
This is a patch release to incorporate the following hotfix:
|
||||
|
||||
* Add back xgboost.rabit for backwards compatibility (#8411)
|
||||
|
||||
|
||||
## v1.7.0 (2022 Oct 20)
|
||||
|
||||
We are excited to announce the feature packed XGBoost 1.7 release. The release note will walk through some of the major new features first, then make a summary for other improvements and language-binding-specific changes.
|
||||
|
||||
### PySpark
|
||||
|
||||
XGBoost 1.7 features initial support for PySpark integration. The new interface is adapted from the existing PySpark XGBoost interface developed by databricks with additional features like `QuantileDMatrix` and the rapidsai plugin (GPU pipeline) support. The new Spark XGBoost Python estimators not only benefit from PySpark ml facilities for powerful distributed computing but also enjoy the rest of the Python ecosystem. Users can define a custom objective, callbacks, and metrics in Python and use them with this interface on distributed clusters. The support is labeled as experimental with more features to come in future releases. For a brief introduction please visit the tutorial on XGBoost's [document page](https://xgboost.readthedocs.io/en/latest/tutorials/spark_estimator.html). (#8355, #8344, #8335, #8284, #8271, #8283, #8250, #8231, #8219, #8245, #8217, #8200, #8173, #8172, #8145, #8117, #8131, #8088, #8082, #8085, #8066, #8068, #8067, #8020, #8385)
|
||||
|
||||
Due to its initial support status, the new interface has some limitations; categorical features and multi-output models are not yet supported.
|
||||
|
||||
### Development of categorical data support
|
||||
More progress on the experimental support for categorical features. In 1.7, XGBoost can handle missing values in categorical features and features a new parameter `max_cat_threshold`, which limits the number of categories that can be used in the split evaluation. The parameter is enabled when the partitioning algorithm is used and helps prevent over-fitting. Also, the sklearn interface can now accept the `feature_types` parameter to use data types other than dataframe for categorical features. (#8280, #7821, #8285, #8080, #7948, #7858, #7853, #8212, #7957, #7937, #7934)
|
||||
|
||||
|
||||
### Experimental support for federated learning and new communication collective
|
||||
|
||||
An exciting addition to XGBoost is the experimental federated learning support. The federated learning is implemented with a gRPC federated server that aggregates allreduce calls, and federated clients that train on local data and use existing tree methods (approx, hist, gpu_hist). Currently, this only supports horizontal federated learning (samples are split across participants, and each participant has all the features and labels). Future plans include vertical federated learning (features split across participants), and stronger privacy guarantees with homomorphic encryption and differential privacy. See [Demo with NVFlare integration](demo/nvflare/README.md) for example usage with nvflare.
|
||||
|
||||
As part of the work, XGBoost 1.7 has replaced the old rabit module with the new collective module as the network communication interface with added support for runtime backend selection. In previous versions, the backend is defined at compile time and can not be changed once built. In this new release, users can choose between `rabit` and `federated.` (#8029, #8351, #8350, #8342, #8340, #8325, #8279, #8181, #8027, #7958, #7831, #7879, #8257, #8316, #8242, #8057, #8203, #8038, #7965, #7930, #7911)
|
||||
|
||||
The feature is available in the public PyPI binary package for testing.
|
||||
|
||||
### Quantile DMatrix
|
||||
Before 1.7, XGBoost has an internal data structure called `DeviceQuantileDMatrix` (and its distributed version). We now extend its support to CPU and renamed it to `QuantileDMatrix`. This data structure is used for optimizing memory usage for the `hist` and `gpu_hist` tree methods. The new feature helps reduce CPU memory usage significantly, especially for dense data. The new `QuantileDMatrix` can be initialized from both CPU and GPU data, and regardless of where the data comes from, the constructed instance can be used by both the CPU algorithm and GPU algorithm including training and prediction (with some overhead of conversion if the device of data and training algorithm doesn't match). Also, a new parameter `ref` is added to `QuantileDMatrix`, which can be used to construct validation/test datasets. Lastly, it's set as default in the scikit-learn interface when a supported tree method is specified by users. (#7889, #7923, #8136, #8215, #8284, #8268, #8220, #8346, #8327, #8130, #8116, #8103, #8094, #8086, #7898, #8060, #8019, #8045, #7901, #7912, #7922)
|
||||
|
||||
### Mean absolute error
|
||||
The mean absolute error is a new member of the collection of objectives in XGBoost. It's noteworthy since MAE has zero hessian value, which is unusual to XGBoost as XGBoost relies on Newton optimization. Without valid Hessian values, the convergence speed can be slow. As part of the support for MAE, we added line searches into the XGBoost training algorithm to overcome the difficulty of training without valid Hessian values. In the future, we will extend the line search to other objectives where it's appropriate for faster convergence speed. (#8343, #8107, #7812, #8380)
|
||||
|
||||
### XGBoost on Browser
|
||||
With the help of the [pyodide](https://github.com/pyodide/pyodide) project, you can now run XGBoost on browsers. (#7954, #8369)
|
||||
|
||||
### Experimental IPv6 Support for Dask
|
||||
|
||||
With the growing adaption of the new internet protocol, XGBoost joined the club. In the latest release, the Dask interface can be used on IPv6 clusters, see XGBoost's Dask tutorial for details. (#8225, #8234)
|
||||
|
||||
### Optimizations
|
||||
We have new optimizations for both the `hist` and `gpu_hist` tree methods to make XGBoost's training even more efficient.
|
||||
|
||||
* Hist
|
||||
Hist now supports optional by-column histogram build, which is automatically configured based on various conditions of input data. This helps the XGBoost CPU hist algorithm to scale better with different shapes of training datasets. (#8233, #8259). Also, the build histogram kernel now can better utilize CPU registers (#8218)
|
||||
|
||||
* GPU Hist
|
||||
GPU hist performance is significantly improved for wide datasets. GPU hist now supports batched node build, which reduces kernel latency and increases throughput. The improvement is particularly significant when growing deep trees with the default ``depthwise`` policy. (#7919, #8073, #8051, #8118, #7867, #7964, #8026)
|
||||
|
||||
### Breaking Changes
|
||||
Breaking changes made in the 1.7 release are summarized below.
|
||||
- The `grow_local_histmaker` updater is removed. This updater is rarely used in practice and has no test. We decided to remove it and focus have XGBoot focus on other more efficient algorithms. (#7992, #8091)
|
||||
- Single precision histogram is removed due to its lack of accuracy caused by significant floating point error. In some cases the error can be difficult to detect due to log-scale operations, which makes the parameter dangerous to use. (#7892, #7828)
|
||||
- Deprecated CUDA architectures are no longer supported in the release binaries. (#7774)
|
||||
- As part of the federated learning development, the `rabit` module is replaced with the new `collective` module. It's a drop-in replacement with added runtime backend selection, see the federated learning section for more details (#8257)
|
||||
|
||||
### General new features and improvements
|
||||
Before diving into package-specific changes, some general new features other than those listed at the beginning are summarized here.
|
||||
* Users of `DMatrix` and `QuantileDMatrix` can get the data from XGBoost. In previous versions, only getters for meta info like labels are available. The new method is available in Python (`DMatrix::get_data`) and C. (#8269, #8323)
|
||||
* In previous versions, the GPU histogram tree method may generate phantom gradient for missing values due to floating point error. We fixed such an error in this release and XGBoost is much better equated to handle floating point errors when training on GPU. (#8274, #8246)
|
||||
* Parameter validation is no longer experimental. (#8206)
|
||||
* C pointer parameters and JSON parameters are vigorously checked. (#8254, #8254)
|
||||
* Improved handling of JSON model input. (#7953, #7918)
|
||||
* Support IBM i OS (#7920, #8178)
|
||||
|
||||
### Fixes
|
||||
Some noteworthy bug fixes that are not related to specific language binding are listed in this section.
|
||||
* Rename misspelled config parameter for pseudo-Huber (#7904)
|
||||
* Fix feature weights with nested column sampling. (#8100)
|
||||
* Fix loading DMatrix binary in distributed env. (#8149)
|
||||
* Force auc.cc to be statically linked for unusual compiler platforms. (#8039)
|
||||
* New logic for detecting libomp on macos (#8384).
|
||||
|
||||
### Python Package
|
||||
* Python 3.8 is now the minimum required Python version. (#8071)
|
||||
* More progress on type hint support. Except for the new PySpark interface, the XGBoost module is fully typed. (#7742, #7945, #8302, #7914, #8052)
|
||||
* XGBoost now validates the feature names in `inplace_predict`, which also affects the predict function in scikit-learn estimators as it uses `inplace_predict` internally. (#8359)
|
||||
* Users can now get the data from `DMatrix` using `DMatrix::get_data` or `QuantileDMatrix::get_data`.
|
||||
* Show `libxgboost.so` path in build info. (#7893)
|
||||
* Raise import error when using the sklearn module while scikit-learn is missing. (#8049)
|
||||
* Use `config_context` in the sklearn interface. (#8141)
|
||||
* Validate features for inplace prediction. (#8359)
|
||||
* Pandas dataframe handling is refactored to reduce data fragmentation. (#7843)
|
||||
* Support more pandas nullable types (#8262)
|
||||
* Remove pyarrow workaround. (#7884)
|
||||
|
||||
* Binary wheel size
|
||||
We aim to enable as many features as possible in XGBoost's default binary distribution on PyPI (package installed with pip), but there's a upper limit on the size of the binary wheel. In 1.7, XGBoost reduces the size of the wheel by pruning unused CUDA architectures. (#8179, #8152, #8150)
|
||||
|
||||
* Fixes
|
||||
Some noteworthy fixes are listed here:
|
||||
- Fix the Dask interface with the latest cupy. (#8210)
|
||||
- Check cuDF lazily to avoid potential errors with cuda-python. (#8084)
|
||||
* Fix potential error in DMatrix constructor on 32-bit platform. (#8369)
|
||||
|
||||
* Maintenance work
|
||||
- Linter script is moved from dmlc-core to XGBoost with added support for formatting, mypy, and parallel run, along with some fixes (#7967, #8101, #8216)
|
||||
- We now require the use of `isort` and `black` for selected files. (#8137, #8096)
|
||||
- Code cleanups. (#7827)
|
||||
- Deprecate `use_label_encoder` in XGBClassifier. The label encoder has already been deprecated and removed in the previous version. These changes only affect the indicator parameter (#7822)
|
||||
- Remove the use of distutils. (#7770)
|
||||
- Refactor and fixes for tests (#8077, #8064, #8078, #8076, #8013, #8010, #8244, #7833)
|
||||
|
||||
* Documents
|
||||
- [dask] Fix potential error in demo. (#8079)
|
||||
- Improved documentation for the ranker. (#8356, #8347)
|
||||
- Indicate lack of py-xgboost-gpu on Windows (#8127)
|
||||
- Clarification for feature importance. (#8151)
|
||||
- Simplify Python getting started example (#8153)
|
||||
|
||||
### R Package
|
||||
We summarize improvements for the R package briefly here:
|
||||
* Feature info including names and types are now passed to DMatrix in preparation for categorical feature support. (#804)
|
||||
* XGBoost 1.7 can now gracefully load old R models from RDS for better compatibility with 3-party tuning libraries (#7864)
|
||||
* The R package now can be built with parallel compilation, along with fixes for warnings in CRAN tests. (#8330)
|
||||
* Emit error early if DiagrammeR is missing (#8037)
|
||||
* Fix R package Windows build. (#8065)
|
||||
|
||||
### JVM Packages
|
||||
The consistency between JVM packages and other language bindings is greatly improved in 1.7, improvements range from model serialization format to the default value of hyper-parameters.
|
||||
|
||||
* Java package now supports feature names and feature types for DMatrix in preparation for categorical feature support. (#7966)
|
||||
* Models trained by the JVM packages can now be safely used with other language bindings. (#7896, #7907)
|
||||
* Users can specify the model format when saving models with a stream. (#7940, #7955)
|
||||
* The default value for training parameters is now sourced from XGBoost directly, which helps JVM packages be consistent with other packages. (#7938)
|
||||
* Set the correct objective if the user doesn't explicitly set it (#7781)
|
||||
* Auto-detection of MUSL is replaced by system properties (#7921)
|
||||
* Improved error message for launching tracker. (#7952, #7968)
|
||||
* Fix a race condition in parameter configuration. (#8025)
|
||||
* [Breaking] ` timeoutRequestWorkers` is now removed. With the support for barrier mode, this parameter is no longer needed. (#7839)
|
||||
* Dependencies updates. (#7791, #8157, #7801, #8240)
|
||||
|
||||
### Documents
|
||||
- Document for the C interface is greatly improved and is now displayed at the [sphinx document page](https://xgboost.readthedocs.io/en/latest/c.html). Thanks to the breathe project, you can view the C API just like the Python API. (#8300)
|
||||
- We now avoid having XGBoost internal text parser in demos and recommend users use dedicated libraries for loading data whenever it's feasible. (#7753)
|
||||
- Python survival training demos are now displayed at [sphinx gallery](https://xgboost.readthedocs.io/en/latest/python/survival-examples/index.html). (#8328)
|
||||
- Some typos, links, format, and grammar fixes. (#7800, #7832, #7861, #8099, #8163, #8166, #8229, #8028, #8214, #7777, #7905, #8270, #8309, d70e59fef, #7806)
|
||||
- Updated winning solution under readme.md (#7862)
|
||||
- New security policy. (#8360)
|
||||
- GPU document is overhauled as we consider CUDA support to be feature-complete. (#8378)
|
||||
|
||||
### Maintenance
|
||||
* Code refactoring and cleanups. (#7850, #7826, #7910, #8332, #8204)
|
||||
* Reduce compiler warnings. (#7768, #7916, #8046, #8059, #7974, #8031, #8022)
|
||||
* Compiler workarounds. (#8211, #8314, #8226, #8093)
|
||||
* Dependencies update. (#8001, #7876, #7973, #8298, #7816)
|
||||
* Remove warnings emitted in previous versions. (#7815)
|
||||
* Small fixes occurred during development. (#8008)
|
||||
|
||||
### CI and Tests
|
||||
* We overhauled the CI infrastructure to reduce the CI cost and lift the maintenance burdens. Jenkins is replaced with buildkite for better automation, with which, finer control of test runs is implemented to reduce overall cost. Also, we refactored some of the existing tests to reduce their runtime, drooped the size of docker images, and removed multi-GPU C++ tests. Lastly, `pytest-timeout` is added as an optional dependency for running Python tests to keep the test time in check. (#7772, #8291, #8286, #8276, #8306, #8287, #8243, #8313, #8235, #8288, #8303, #8142, #8092, #8333, #8312, #8348)
|
||||
* New documents for how to reproduce the CI environment (#7971, #8297)
|
||||
* Improved automation for JVM release. (#7882)
|
||||
* GitHub Action security-related updates. (#8263, #8267, #8360)
|
||||
* Other fixes and maintenance work. (#8154, #7848, #8069, #7943)
|
||||
* Small updates and fixes to GitHub action pipelines. (#8364, #8321, #8241, #7950, #8011)
|
||||
|
||||
## v1.6.1 (2022 May 9)
|
||||
This is a patch release for bug fixes and Spark barrier mode support. The R package is unchanged.
|
||||
|
||||
### Experimental support for categorical data
|
||||
- Fix segfault when the number of samples is smaller than the number of categories. (https://github.com/dmlc/xgboost/pull/7853)
|
||||
- Enable partition-based split for all model types. (https://github.com/dmlc/xgboost/pull/7857)
|
||||
|
||||
### JVM packages
|
||||
We replaced the old parallelism tracker with spark barrier mode to improve the robustness of the JVM package and fix the GPU training pipeline.
|
||||
- Fix GPU training pipeline quantile synchronization. (#7823, #7834)
|
||||
- Use barrier model in spark package. (https://github.com/dmlc/xgboost/pull/7836, https://github.com/dmlc/xgboost/pull/7840, https://github.com/dmlc/xgboost/pull/7845, https://github.com/dmlc/xgboost/pull/7846)
|
||||
- Fix shared object loading on some platforms. (https://github.com/dmlc/xgboost/pull/7844)
|
||||
|
||||
## v1.6.0 (2022 Apr 16)
|
||||
|
||||
After a long period of development, XGBoost v1.6.0 is packed with many new features and
|
||||
improvements. We summarize them in the following sections starting with an introduction to
|
||||
some major new features, then moving on to language binding specific changes including new
|
||||
features and notable bug fixes for that binding.
|
||||
|
||||
### Development of categorical data support
|
||||
This version of XGBoost features new improvements and full coverage of experimental
|
||||
categorical data support in Python and C package with tree model. Both `hist`, `approx`
|
||||
and `gpu_hist` now support training with categorical data. Also, partition-based
|
||||
categorical split is introduced in this release. This split type is first available in
|
||||
LightGBM in the context of gradient boosting. The previous XGBoost release supported one-hot split where the splitting criteria is of form `x \in {c}`, i.e. the categorical feature `x` is tested against a single candidate. The new release allows for more expressive conditions: `x \in S` where the categorical feature `x` is tested against multiple candidates. Moreover, it is now possible to use any tree algorithms (`hist`, `approx`, `gpu_hist`) when creating categorical splits. For more
|
||||
information, please see our tutorial on [categorical
|
||||
data](https://xgboost.readthedocs.io/en/latest/tutorials/categorical.html), along with
|
||||
examples linked on that page. (#7380, #7708, #7695, #7330, #7307, #7322, #7705,
|
||||
#7652, #7592, #7666, #7576, #7569, #7529, #7575, #7393, #7465, #7385, #7371, #7745, #7810)
|
||||
|
||||
In the future, we will continue to improve categorical data support with new features and
|
||||
optimizations. Also, we are looking forward to bringing the feature beyond Python binding,
|
||||
contributions and feedback are welcomed! Lastly, as a result of experimental status, the
|
||||
behavior might be subject to change, especially the default value of related
|
||||
hyper-parameters.
|
||||
|
||||
### Experimental support for multi-output model
|
||||
|
||||
XGBoost 1.6 features initial support for the multi-output model, which includes
|
||||
multi-output regression and multi-label classification. Along with this, the XGBoost
|
||||
classifier has proper support for base margin without to need for the user to flatten the
|
||||
input. In this initial support, XGBoost builds one model for each target similar to the
|
||||
sklearn meta estimator, for more details, please see our [quick
|
||||
introduction](https://xgboost.readthedocs.io/en/latest/tutorials/multioutput.html).
|
||||
|
||||
(#7365, #7736, #7607, #7574, #7521, #7514, #7456, #7453, #7455, #7434, #7429, #7405, #7381)
|
||||
|
||||
### External memory support
|
||||
External memory support for both approx and hist tree method is considered feature
|
||||
complete in XGBoost 1.6. Building upon the iterator-based interface introduced in the
|
||||
previous version, now both `hist` and `approx` iterates over each batch of data during
|
||||
training and prediction. In previous versions, `hist` concatenates all the batches into
|
||||
an internal representation, which is removed in this version. As a result, users can
|
||||
expect higher scalability in terms of data size but might experience lower performance due
|
||||
to disk IO. (#7531, #7320, #7638, #7372)
|
||||
|
||||
### Rewritten approx
|
||||
|
||||
The `approx` tree method is rewritten based on the existing `hist` tree method. The
|
||||
rewrite closes the feature gap between `approx` and `hist` and improves the performance.
|
||||
Now the behavior of `approx` should be more aligned with `hist` and `gpu_hist`. Here is a
|
||||
list of user-visible changes:
|
||||
|
||||
- Supports both `max_leaves` and `max_depth`.
|
||||
- Supports `grow_policy`.
|
||||
- Supports monotonic constraint.
|
||||
- Supports feature weights.
|
||||
- Use `max_bin` to replace `sketch_eps`.
|
||||
- Supports categorical data.
|
||||
- Faster performance for many of the datasets.
|
||||
- Improved performance and robustness for distributed training.
|
||||
- Supports prediction cache.
|
||||
- Significantly better performance for external memory when `depthwise` policy is used.
|
||||
|
||||
### New serialization format
|
||||
Based on the existing JSON serialization format, we introduce UBJSON support as a more
|
||||
efficient alternative. Both formats will be available in the future and we plan to
|
||||
gradually [phase out](https://github.com/dmlc/xgboost/issues/7547) support for the old
|
||||
binary model format. Users can opt to use the different formats in the serialization
|
||||
function by providing the file extension `json` or `ubj`. Also, the `save_raw` function in
|
||||
all supported languages bindings gains a new parameter for exporting the model in different
|
||||
formats, available options are `json`, `ubj`, and `deprecated`, see document for the
|
||||
language binding you are using for details. Lastly, the default internal serialization
|
||||
format is set to UBJSON, which affects Python pickle and R RDS. (#7572, #7570, #7358,
|
||||
#7571, #7556, #7549, #7416)
|
||||
|
||||
### General new features and improvements
|
||||
Aside from the major new features mentioned above, some others are summarized here:
|
||||
|
||||
* Users can now access the build information of XGBoost binary in Python and C
|
||||
interface. (#7399, #7553)
|
||||
* Auto-configuration of `seed_per_iteration` is removed, now distributed training should
|
||||
generate closer results to single node training when sampling is used. (#7009)
|
||||
* A new parameter `huber_slope` is introduced for the `Pseudo-Huber` objective.
|
||||
* During source build, XGBoost can choose cub in the system path automatically. (#7579)
|
||||
* XGBoost now honors the CPU counts from CFS, which is usually set in docker
|
||||
environments. (#7654, #7704)
|
||||
* The metric `aucpr` is rewritten for better performance and GPU support. (#7297, #7368)
|
||||
* Metric calculation is now performed in double precision. (#7364)
|
||||
* XGBoost no longer mutates the global OpenMP thread limit. (#7537, #7519, #7608, #7590,
|
||||
#7589, #7588, #7687)
|
||||
* The default behavior of `max_leave` and `max_depth` is now unified (#7302, #7551).
|
||||
* CUDA fat binary is now compressed. (#7601)
|
||||
* Deterministic result for evaluation metric and linear model. In previous versions of
|
||||
XGBoost, evaluation results might differ slightly for each run due to parallel reduction
|
||||
for floating-point values, which is now addressed. (#7362, #7303, #7316, #7349)
|
||||
* XGBoost now uses double for GPU Hist node sum, which improves the accuracy of
|
||||
`gpu_hist`. (#7507)
|
||||
|
||||
### Performance improvements
|
||||
Most of the performance improvements are integrated into other refactors during feature
|
||||
developments. The `approx` should see significant performance gain for many datasets as
|
||||
mentioned in the previous section, while the `hist` tree method also enjoys improved
|
||||
performance with the removal of the internal `pruner` along with some other
|
||||
refactoring. Lastly, `gpu_hist` no longer synchronizes the device during training. (#7737)
|
||||
|
||||
### General bug fixes
|
||||
This section lists bug fixes that are not specific to any language binding.
|
||||
* The `num_parallel_tree` is now a model parameter instead of a training hyper-parameter,
|
||||
which fixes model IO with random forest. (#7751)
|
||||
* Fixes in CMake script for exporting configuration. (#7730)
|
||||
* XGBoost can now handle unsorted sparse input. This includes text file formats like
|
||||
libsvm and scipy sparse matrix where column index might not be sorted. (#7731)
|
||||
* Fix tree param feature type, this affects inputs with the number of columns greater than
|
||||
the maximum value of int32. (#7565)
|
||||
* Fix external memory with gpu_hist and subsampling. (#7481)
|
||||
* Check the number of trees in inplace predict, this avoids a potential segfault when an
|
||||
incorrect value for `iteration_range` is provided. (#7409)
|
||||
* Fix non-stable result in cox regression (#7756)
|
||||
|
||||
### Changes in the Python package
|
||||
Other than the changes in Dask, the XGBoost Python package gained some new features and
|
||||
improvements along with small bug fixes.
|
||||
|
||||
* Python 3.7 is required as the lowest Python version. (#7682)
|
||||
* Pre-built binary wheel for Apple Silicon. (#7621, #7612, #7747) Apple Silicon users will
|
||||
now be able to run `pip install xgboost` to install XGBoost.
|
||||
* MacOS users no longer need to install `libomp` from Homebrew, as the XGBoost wheel now
|
||||
bundles `libomp.dylib` library.
|
||||
* There are new parameters for users to specify the custom metric with new
|
||||
behavior. XGBoost can now output transformed prediction values when a custom objective is
|
||||
not supplied. See our explanation in the
|
||||
[tutorial](https://xgboost.readthedocs.io/en/latest/tutorials/custom_metric_obj.html#reverse-link-function)
|
||||
for details.
|
||||
* For the sklearn interface, following the estimator guideline from scikit-learn, all
|
||||
parameters in `fit` that are not related to input data are moved into the constructor
|
||||
and can be set by `set_params`. (#6751, #7420, #7375, #7369)
|
||||
* Apache arrow format is now supported, which can bring better performance to users'
|
||||
pipeline (#7512)
|
||||
* Pandas nullable types are now supported (#7760)
|
||||
* A new function `get_group` is introduced for `DMatrix` to allow users to get the group
|
||||
information in the custom objective function. (#7564)
|
||||
* More training parameters are exposed in the sklearn interface instead of relying on the
|
||||
`**kwargs`. (#7629)
|
||||
* A new attribute `feature_names_in_` is defined for all sklearn estimators like
|
||||
`XGBRegressor` to follow the convention of sklearn. (#7526)
|
||||
* More work on Python type hint. (#7432, #7348, #7338, #7513, #7707)
|
||||
* Support the latest pandas Index type. (#7595)
|
||||
* Fix for Feature shape mismatch error on s390x platform (#7715)
|
||||
* Fix using feature names for constraints with multiple groups (#7711)
|
||||
* We clarified the behavior of the callback function when it contains mutable
|
||||
states. (#7685)
|
||||
* Lastly, there are some code cleanups and maintenance work. (#7585, #7426, #7634, #7665,
|
||||
#7667, #7377, #7360, #7498, #7438, #7667, #7752, #7749, #7751)
|
||||
|
||||
### Changes in the Dask interface
|
||||
* Dask module now supports user-supplied host IP and port address of scheduler node.
|
||||
Please see [introduction](https://xgboost.readthedocs.io/en/latest/tutorials/dask.html#troubleshooting) and
|
||||
[API document](https://xgboost.readthedocs.io/en/latest/python/python_api.html#optional-dask-configuration)
|
||||
for reference. (#7645, #7581)
|
||||
* Internal `DMatrix` construction in dask now honers thread configuration. (#7337)
|
||||
* A fix for `nthread` configuration using the Dask sklearn interface. (#7633)
|
||||
* The Dask interface can now handle empty partitions. An empty partition is different
|
||||
from an empty worker, the latter refers to the case when a worker has no partition of an
|
||||
input dataset, while the former refers to some partitions on a worker that has zero
|
||||
sizes. (#7644, #7510)
|
||||
* Scipy sparse matrix is supported as Dask array partition. (#7457)
|
||||
* Dask interface is no longer considered experimental. (#7509)
|
||||
|
||||
### Changes in the R package
|
||||
This section summarizes the new features, improvements, and bug fixes to the R package.
|
||||
|
||||
* `load.raw` can optionally construct a booster as return. (#7686)
|
||||
* Fix parsing decision stump, which affects both transforming text representation to data
|
||||
table and plotting. (#7689)
|
||||
* Implement feature weights. (#7660)
|
||||
* Some improvements for complying the CRAN release policy. (#7672, #7661, #7763)
|
||||
* Support CSR data for predictions (#7615)
|
||||
* Document update (#7263, #7606)
|
||||
* New maintainer for the CRAN package (#7691, #7649)
|
||||
* Handle non-standard installation of toolchain on macos (#7759)
|
||||
|
||||
### Changes in JVM-packages
|
||||
Some new features for JVM-packages are introduced for a more integrated GPU pipeline and
|
||||
better compatibility with musl-based Linux. Aside from this, we have a few notable bug
|
||||
fixes.
|
||||
|
||||
* User can specify the tracker IP address for training, which helps running XGBoost on
|
||||
restricted network environments. (#7808)
|
||||
* Add support for detecting musl-based Linux (#7624)
|
||||
* Add `DeviceQuantileDMatrix` to Scala binding (#7459)
|
||||
* Add Rapids plugin support, now more of the JVM pipeline can be accelerated by RAPIDS (#7491, #7779, #7793, #7806)
|
||||
* The setters for CPU and GPU are more aligned (#7692, #7798)
|
||||
* Control logging for early stopping (#7326)
|
||||
* Do not repartition when nWorker = 1 (#7676)
|
||||
* Fix the prediction issue for `multi:softmax` (#7694)
|
||||
* Fix for serialization of custom objective and eval (#7274)
|
||||
* Update documentation about Python tracker (#7396)
|
||||
* Remove jackson from dependency, which fixes CVE-2020-36518. (#7791)
|
||||
* Some refactoring to the training pipeline for better compatibility between CPU and
|
||||
GPU. (#7440, #7401, #7789, #7784)
|
||||
* Maintenance work. (#7550, #7335, #7641, #7523, #6792, #4676)
|
||||
|
||||
### Deprecation
|
||||
Other than the changes in the Python package and serialization, we removed some deprecated
|
||||
features in previous releases. Also, as mentioned in the previous section, we plan to
|
||||
phase out the old binary format in future releases.
|
||||
|
||||
* Remove old warning in 1.3 (#7279)
|
||||
* Remove label encoder deprecated in 1.3. (#7357)
|
||||
* Remove old callback deprecated in 1.3. (#7280)
|
||||
* Pre-built binary will no longer support deprecated CUDA architectures including sm35 and
|
||||
sm50. Users can continue to use these platforms with source build. (#7767)
|
||||
|
||||
### Documentation
|
||||
This section lists some of the general changes to XGBoost's document, for language binding
|
||||
specific change please visit related sections.
|
||||
|
||||
* Document is overhauled to use the new RTD theme, along with integration of Python
|
||||
examples using Sphinx gallery. Also, we replaced most of the hard-coded URLs with sphinx
|
||||
references. (#7347, #7346, #7468, #7522, #7530)
|
||||
* Small update along with fixes for broken links, typos, etc. (#7684, #7324, #7334, #7655,
|
||||
#7628, #7623, #7487, #7532, #7500, #7341, #7648, #7311)
|
||||
* Update document for GPU. [skip ci] (#7403)
|
||||
* Document the status of RTD hosting. (#7353)
|
||||
* Update document for building from source. (#7664)
|
||||
* Add note about CRAN release [skip ci] (#7395)
|
||||
|
||||
### Maintenance
|
||||
This is a summary of maintenance work that is not specific to any language binding.
|
||||
|
||||
* Add CMake option to use /MD runtime (#7277)
|
||||
* Add clang-format configuration. (#7383)
|
||||
* Code cleanups (#7539, #7536, #7466, #7499, #7533, #7735, #7722, #7668, #7304, #7293,
|
||||
#7321, #7356, #7345, #7387, #7577, #7548, #7469, #7680, #7433, #7398)
|
||||
* Improved tests with better coverage and latest dependency (#7573, #7446, #7650, #7520,
|
||||
#7373, #7723, #7611, #7771)
|
||||
* Improved automation of the release process. (#7278, #7332, #7470)
|
||||
* Compiler workarounds (#7673)
|
||||
* Change shebang used in CLI demo. (#7389)
|
||||
* Update affiliation (#7289)
|
||||
|
||||
### CI
|
||||
Some fixes and update to XGBoost's CI infrastructure. (#7739, #7701, #7382, #7662, #7646,
|
||||
#7582, #7407, #7417, #7475, #7474, #7479, #7472, #7626)
|
||||
|
||||
|
||||
## v1.5.0 (2021 Oct 11)
|
||||
|
||||
This release comes with many exciting new features and optimizations, along with some bug
|
||||
fixes. We will describe the experimental categorical data support and the external memory
|
||||
interface independently. Package-specific new features will be listed in respective
|
||||
sections.
|
||||
|
||||
### Development on categorical data support
|
||||
In version 1.3, XGBoost introduced an experimental feature for handling categorical data
|
||||
natively, without one-hot encoding. XGBoost can fit categorical splits in decision
|
||||
trees. (Currently, the generated splits will be of form `x \in {v}`, where the input is
|
||||
compared to a single category value. A future version of XGBoost will generate splits that
|
||||
compare the input against a list of multiple category values.)
|
||||
|
||||
Most of the other features, including prediction, SHAP value computation, feature
|
||||
importance, and model plotting were revised to natively handle categorical splits. Also,
|
||||
all Python interfaces including native interface with and without quantized `DMatrix`,
|
||||
scikit-learn interface, and Dask interface now accept categorical data with a wide range
|
||||
of data structures support including numpy/cupy array and cuDF/pandas/modin dataframe. In
|
||||
practice, the following are required for enabling categorical data support during
|
||||
training:
|
||||
|
||||
- Use Python package.
|
||||
- Use `gpu_hist` to train the model.
|
||||
- Use JSON model file format for saving the model.
|
||||
|
||||
Once the model is trained, it can be used with most of the features that are available on
|
||||
the Python package. For a quick introduction, see
|
||||
https://xgboost.readthedocs.io/en/latest/tutorials/categorical.html
|
||||
|
||||
Related PRs: (#7011, #7001, #7042, #7041, #7047, #7043, #7036, #7054, #7053, #7065, #7213, #7228, #7220, #7221, #7231, #7306)
|
||||
|
||||
* Next steps
|
||||
|
||||
- Revise the CPU training algorithm to handle categorical data natively and generate categorical splits
|
||||
- Extend the CPU and GPU algorithms to generate categorical splits of form `x \in S`
|
||||
where the input is compared with multiple category values. split. (#7081)
|
||||
|
||||
### External memory
|
||||
This release features a brand-new interface and implementation for external memory (also
|
||||
known as out-of-core training). (#6901, #7064, #7088, #7089, #7087, #7092, #7070,
|
||||
#7216). The new implementation leverages the data iterator interface, which is currently
|
||||
used to create `DeviceQuantileDMatrix`. For a quick introduction, see
|
||||
https://xgboost.readthedocs.io/en/latest/tutorials/external_memory.html#data-iterator
|
||||
. During the development of this new interface, `lz4` compression is removed. (#7076).
|
||||
Please note that external memory support is still experimental and not ready for
|
||||
production use yet. All future development will focus on this new interface and users are
|
||||
advised to migrate. (You are using the old interface if you are using a URL suffix to use
|
||||
external memory.)
|
||||
|
||||
### New features in Python package
|
||||
* Support numpy array interface and all numeric types from numpy in `DMatrix`
|
||||
construction and `inplace_predict` (#6998, #7003). Now XGBoost no longer makes data
|
||||
copy when input is numpy array view.
|
||||
* The early stopping callback in Python has a new `min_delta` parameter to control the
|
||||
stopping behavior (#7137)
|
||||
* Python package now supports calculating feature scores for the linear model, which is
|
||||
also available on R package. (#7048)
|
||||
* Python interface now supports configuring constraints using feature names instead of
|
||||
feature indices.
|
||||
* Typehint support for more Python code including scikit-learn interface and rabit
|
||||
module. (#6799, #7240)
|
||||
* Add tutorial for XGBoost-Ray (#6884)
|
||||
|
||||
### New features in R package
|
||||
* In 1.4 we have a new prediction function in the C API which is used by the Python
|
||||
package. This release revises the R package to use the new prediction function as well.
|
||||
A new parameter `iteration_range` for the predict function is available, which can be
|
||||
used for specifying the range of trees for running prediction. (#6819, #7126)
|
||||
* R package now supports the `nthread` parameter in `DMatrix` construction. (#7127)
|
||||
|
||||
### New features in JVM packages
|
||||
* Support GPU dataframe and `DeviceQuantileDMatrix` (#7195). Constructing `DMatrix`
|
||||
with GPU data structures and the interface for quantized `DMatrix` were first
|
||||
introduced in the Python package and are now available in the xgboost4j package.
|
||||
* JVM packages now support saving and getting early stopping attributes. (#7095) Here is a
|
||||
quick [example](https://github.com/dmlc/xgboost/jvm-packages/xgboost4j-example/src/main/java/ml/dmlc/xgboost4j/java/example/EarlyStopping.java "example") in JAVA (#7252).
|
||||
|
||||
### General new features
|
||||
* We now have a pre-built binary package for R on Windows with GPU support. (#7185)
|
||||
* CUDA compute capability 86 is now part of the default CMake build configuration with
|
||||
newly added support for CUDA 11.4. (#7131, #7182, #7254)
|
||||
* XGBoost can be compiled using system CUB provided by CUDA 11.x installation. (#7232)
|
||||
|
||||
### Optimizations
|
||||
The performance for both `hist` and `gpu_hist` has been significantly improved in 1.5
|
||||
with the following optimizations:
|
||||
* GPU multi-class model training now supports prediction cache. (#6860)
|
||||
* GPU histogram building is sped up and the overall training time is 2-3 times faster on
|
||||
large datasets (#7180, #7198). In addition, we removed the parameter `deterministic_histogram` and now
|
||||
the GPU algorithm is always deterministic.
|
||||
* CPU hist has an optimized procedure for data sampling (#6922)
|
||||
* More performance optimization in regression and binary classification objectives on
|
||||
CPU (#7206)
|
||||
* Tree model dump is now performed in parallel (#7040)
|
||||
|
||||
### Breaking changes
|
||||
* `n_gpus` was deprecated in 1.0 release and is now removed.
|
||||
* Feature grouping in CPU hist tree method is removed, which was disabled long
|
||||
ago. (#7018)
|
||||
* C API for Quantile DMatrix is changed to be consistent with the new external memory
|
||||
implementation. (#7082)
|
||||
|
||||
### Notable general bug fixes
|
||||
* XGBoost no long changes global CUDA device ordinal when `gpu_id` is specified (#6891,
|
||||
#6987)
|
||||
* Fix `gamma` negative likelihood evaluation metric. (#7275)
|
||||
* Fix integer value of `verbose_eal` for `xgboost.cv` function in Python. (#7291)
|
||||
* Remove extra sync in CPU hist for dense data, which can lead to incorrect tree node
|
||||
statistics. (#7120, #7128)
|
||||
* Fix a bug in GPU hist when data size is larger than `UINT32_MAX` with missing
|
||||
values. (#7026)
|
||||
* Fix a thread safety issue in prediction with the `softmax` objective. (#7104)
|
||||
* Fix a thread safety issue in CPU SHAP value computation. (#7050) Please note that all
|
||||
prediction functions in Python are thread-safe.
|
||||
* Fix model slicing. (#7149, #7078)
|
||||
* Workaround a bug in old GCC which can lead to segfault during construction of
|
||||
DMatrix. (#7161)
|
||||
* Fix histogram truncation in GPU hist, which can lead to slightly-off results. (#7181)
|
||||
* Fix loading GPU linear model pickle files on CPU-only machine. (#7154)
|
||||
* Check input value is duplicated when CPU quantile queue is full (#7091)
|
||||
* Fix parameter loading with training continuation. (#7121)
|
||||
* Fix CMake interface for exposing C library by specifying dependencies. (#7099)
|
||||
* Callback and early stopping are explicitly disabled for the scikit-learn interface
|
||||
random forest estimator. (#7236)
|
||||
* Fix compilation error on x86 (32-bit machine) (#6964)
|
||||
* Fix CPU memory usage with extremely sparse datasets (#7255)
|
||||
* Fix a bug in GPU multi-class AUC implementation with weighted data (#7300)
|
||||
|
||||
### Python package
|
||||
Other than the items mentioned in the previous sections, there are some Python-specific
|
||||
improvements.
|
||||
* Change development release postfix to `dev` (#6988)
|
||||
* Fix early stopping behavior with MAPE metric (#7061)
|
||||
* Fixed incorrect feature mismatch error message (#6949)
|
||||
* Add predictor to skl constructor. (#7000, #7159)
|
||||
* Re-enable feature validation in predict proba. (#7177)
|
||||
* scikit learn interface regression estimator now can pass the scikit-learn estimator
|
||||
check and is fully compatible with scikit-learn utilities. `__sklearn_is_fitted__` is
|
||||
implemented as part of the changes (#7130, #7230)
|
||||
* Conform the latest pylint. (#7071, #7241)
|
||||
* Support latest panda range index in DMatrix construction. (#7074)
|
||||
* Fix DMatrix construction from pandas series. (#7243)
|
||||
* Fix typo and grammatical mistake in error message (#7134)
|
||||
* [dask] disable work stealing explicitly for training tasks (#6794)
|
||||
* [dask] Set dataframe index in predict. (#6944)
|
||||
* [dask] Fix prediction on df with latest dask. (#6969)
|
||||
* [dask] Fix dask predict on `DaskDMatrix` with `iteration_range`. (#7005)
|
||||
* [dask] Disallow importing non-dask estimators from xgboost.dask (#7133)
|
||||
|
||||
### R package
|
||||
Improvements other than new features on R package:
|
||||
* Optimization for updating R handles in-place (#6903)
|
||||
* Removed the magrittr dependency. (#6855, #6906, #6928)
|
||||
* The R package now hides all C++ symbols to avoid conflicts. (#7245)
|
||||
* Other maintenance including code cleanups, document updates. (#6863, #6915, #6930, #6966, #6967)
|
||||
|
||||
### JVM packages
|
||||
Improvements other than new features on JVM packages:
|
||||
* Constructors with implicit missing value are deprecated due to confusing behaviors. (#7225)
|
||||
* Reduce scala-compiler, scalatest dependency scopes (#6730)
|
||||
* Making the Java library loader emit helpful error messages on missing dependencies. (#6926)
|
||||
* JVM packages now use the Python tracker in XGBoost instead of dmlc. The one in XGBoost
|
||||
is shared between JVM packages and Python Dask and enjoys better maintenance (#7132)
|
||||
* Fix "key not found: train" error (#6842)
|
||||
* Fix model loading from stream (#7067)
|
||||
|
||||
### General document improvements
|
||||
* Overhaul the installation documents. (#6877)
|
||||
* A few demos are added for AFT with dask (#6853), callback with dask (#6995), inference
|
||||
in C (#7151), `process_type`. (#7135)
|
||||
* Fix PDF format of document. (#7143)
|
||||
* Clarify the behavior of `use_rmm`. (#6808)
|
||||
* Clarify prediction function. (#6813)
|
||||
* Improve tutorial on feature interactions (#7219)
|
||||
* Add small example for dask sklearn interface. (#6970)
|
||||
* Update Python intro. (#7235)
|
||||
* Some fixes/updates (#6810, #6856, #6935, #6948, #6976, #7084, #7097, #7170, #7173, #7174, #7226, #6979, #6809, #6796, #6979)
|
||||
|
||||
### Maintenance
|
||||
* Some refactoring around CPU hist, which lead to better performance but are listed under general maintenance tasks:
|
||||
- Extract evaluate splits from CPU hist. (#7079)
|
||||
- Merge lossgude and depthwise strategies for CPU hist (#7007)
|
||||
- Simplify sparse and dense CPU hist kernels (#7029)
|
||||
- Extract histogram builder from CPU Hist. (#7152)
|
||||
|
||||
* Others
|
||||
- Fix `gpu_id` with custom objective. (#7015)
|
||||
- Fix typos in AUC. (#6795)
|
||||
- Use constexpr in `dh::CopyIf`. (#6828)
|
||||
- Update dmlc-core. (#6862)
|
||||
- Bump version to 1.5.0 snapshot in master. (#6875)
|
||||
- Relax shotgun test. (#6900)
|
||||
- Guard against index error in prediction. (#6982)
|
||||
- Hide symbols in CI build + hide symbols for C and CUDA (#6798)
|
||||
- Persist data in dask test. (#7077)
|
||||
- Fix typo in arguments of PartitionBuilder::Init (#7113)
|
||||
- Fix typo in src/common/hist.cc BuildHistKernel (#7116)
|
||||
- Use upstream URI in distributed quantile tests. (#7129)
|
||||
- Include cpack (#7160)
|
||||
- Remove synchronization in monitor. (#7164)
|
||||
- Remove unused code. (#7175)
|
||||
- Fix building on CUDA 11.0. (#7187)
|
||||
- Better error message for `ncclUnhandledCudaError`. (#7190)
|
||||
- Add noexcept to JSON objects. (#7205)
|
||||
- Improve wording for warning (#7248)
|
||||
- Fix typo in release script. [skip ci] (#7238)
|
||||
- Relax shotgun test. (#6918)
|
||||
- Relax test for decision stump in distributed environment. (#6919)
|
||||
- [dask] speed up tests (#7020)
|
||||
|
||||
### CI
|
||||
* [CI] Rotate access keys for uploading MacOS artifacts from Travis CI (#7253)
|
||||
* Reduce Travis environment setup time. (#6912)
|
||||
* Restore R cache on github action. (#6985)
|
||||
* [CI] Remove stray build artifact to avoid error in artifact packaging (#6994)
|
||||
* [CI] Move appveyor tests to action (#6986)
|
||||
* Remove appveyor badge. [skip ci] (#7035)
|
||||
* [CI] Configure RAPIDS, dask, modin (#7033)
|
||||
* Test on s390x. (#7038)
|
||||
* [CI] Upgrade to CMake 3.14 (#7060)
|
||||
* [CI] Update R cache. (#7102)
|
||||
* [CI] Pin libomp to 11.1.0 (#7107)
|
||||
* [CI] Upgrade build image to CentOS 7 + GCC 8; require CUDA 10.1 and later (#7141)
|
||||
* [dask] Work around segfault in prediction. (#7112)
|
||||
* [dask] Remove the workaround for segfault. (#7146)
|
||||
* [CI] Fix hanging Python setup in Windows CI (#7186)
|
||||
* [CI] Clean up in beginning of each task in Win CI (#7189)
|
||||
* Fix travis. (#7237)
|
||||
|
||||
### Acknowledgement
|
||||
* **Contributors**: Adam Pocock (@Craigacp), Jeff H (@JeffHCross), Johan Hansson (@JohanWork), Jose Manuel Llorens (@JoseLlorensRipolles), Benjamin Szőke (@Livius90), @ReeceGoding, @ShvetsKS, Robert Zabel (@ZabelTech), Ali (@ali5h), Andrew Ziem (@az0), Andy Adinets (@canonizer), @david-cortes, Daniel Saxton (@dsaxton), Emil Sadek (@esadek), @farfarawayzyt, Gil Forsyth (@gforsyth), @giladmaya, @graue70, Philip Hyunsu Cho (@hcho3), James Lamb (@jameslamb), José Morales (@jmoralez), Kai Fricke (@krfricke), Christian Lorentzen (@lorentzenchr), Mads R. B. Kristensen (@madsbk), Anton Kostin (@masguit42), Martin Petříček (@mpetricek-corp), @naveenkb, Taewoo Kim (@oOTWK), Viktor Szathmáry (@phraktle), Robert Maynard (@robertmaynard), TP Boudreau (@tpboudreau), Jiaming Yuan (@trivialfis), Paul Taylor (@trxcllnt), @vslaykovsky, Bobby Wang (@wbo4958),
|
||||
* **Reviewers**: Nan Zhu (@CodingCat), Adam Pocock (@Craigacp), Jose Manuel Llorens (@JoseLlorensRipolles), Kodi Arfer (@Kodiologist), Benjamin Szőke (@Livius90), Mark Guryanov (@MarkGuryanov), Rory Mitchell (@RAMitchell), @ReeceGoding, @ShvetsKS, Egor Smirnov (@SmirnovEgorRu), Andrew Ziem (@az0), @candalfigomoro, Andy Adinets (@canonizer), Dante Gama Dessavre (@dantegd), @david-cortes, Daniel Saxton (@dsaxton), @farfarawayzyt, Gil Forsyth (@gforsyth), Harutaka Kawamura (@harupy), Philip Hyunsu Cho (@hcho3), @jakirkham, James Lamb (@jameslamb), José Morales (@jmoralez), James Bourbeau (@jrbourbeau), Christian Lorentzen (@lorentzenchr), Martin Petříček (@mpetricek-corp), Nikolay Petrov (@napetrov), @naveenkb, Viktor Szathmáry (@phraktle), Robin Teuwens (@rteuwens), Yuan Tang (@terrytangyuan), TP Boudreau (@tpboudreau), Jiaming Yuan (@trivialfis), @vkuzmin-uber, Bobby Wang (@wbo4958), William Hicks (@wphicks)
|
||||
|
||||
|
||||
## v1.4.2 (2021.05.13)
|
||||
This is a patch release for Python package with following fixes:
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ target_compile_definitions(xgboost-r
|
||||
-DDMLC_LOG_BEFORE_THROW=0
|
||||
-DDMLC_DISABLE_STDIN=1
|
||||
-DDMLC_LOG_CUSTOMIZE=1
|
||||
-DRABIT_CUSTOMIZE_MSG_
|
||||
-DRABIT_STRICT_CXX98_)
|
||||
target_include_directories(xgboost-r
|
||||
PRIVATE
|
||||
@@ -30,7 +31,7 @@ if (USE_OPENMP)
|
||||
endif (USE_OPENMP)
|
||||
set_target_properties(
|
||||
xgboost-r PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Package: xgboost
|
||||
Type: Package
|
||||
Title: Extreme Gradient Boosting
|
||||
Version: 2.0.0.1
|
||||
Date: 2022-10-18
|
||||
Version: 1.5.0.1
|
||||
Date: 2021-09-25
|
||||
Authors@R: c(
|
||||
person("Tianqi", "Chen", role = c("aut"),
|
||||
email = "tianqi.tchen@gmail.com"),
|
||||
person("Tong", "He", role = c("aut"),
|
||||
person("Tong", "He", role = c("aut", "cre"),
|
||||
email = "hetong007@gmail.com"),
|
||||
person("Michael", "Benesty", role = c("aut"),
|
||||
email = "michael@benesty.fr"),
|
||||
@@ -26,12 +26,9 @@ Authors@R: c(
|
||||
person("Min", "Lin", role = c("aut")),
|
||||
person("Yifeng", "Geng", role = c("aut")),
|
||||
person("Yutian", "Li", role = c("aut")),
|
||||
person("Jiaming", "Yuan", role = c("aut", "cre"),
|
||||
email = "jm.yuan@outlook.com"),
|
||||
person("XGBoost contributors", role = c("cph"),
|
||||
comment = "base XGBoost implementation")
|
||||
)
|
||||
Maintainer: Jiaming Yuan <jm.yuan@outlook.com>
|
||||
Description: Extreme Gradient Boosting, which is an efficient implementation
|
||||
of the gradient boosting framework from Chen & Guestrin (2016) <doi:10.1145/2939672.2939785>.
|
||||
This package is its R interface. The package includes efficient linear
|
||||
@@ -54,8 +51,10 @@ Suggests:
|
||||
Ckmeans.1d.dp (>= 3.3.1),
|
||||
vcd (>= 1.3),
|
||||
testthat,
|
||||
lintr,
|
||||
igraph (>= 1.0.1),
|
||||
float,
|
||||
crayon,
|
||||
titanic
|
||||
Depends:
|
||||
R (>= 3.3.0)
|
||||
@@ -64,6 +63,5 @@ Imports:
|
||||
methods,
|
||||
data.table (>= 1.9.6),
|
||||
jsonlite (>= 1.0),
|
||||
RoxygenNote: 7.2.3
|
||||
Encoding: UTF-8
|
||||
SystemRequirements: GNU make, C++17
|
||||
RoxygenNote: 7.1.1
|
||||
SystemRequirements: GNU make, C++14
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Copyright (c) 2014-2023, Tianqi Chen and XBGoost Contributors
|
||||
Copyright (c) 2014 by Tianqi Chen and Contributors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
@@ -114,7 +114,7 @@ cb.evaluation.log <- function() {
|
||||
if (is.null(mnames) || any(mnames == ""))
|
||||
stop("bst_evaluation must have non-empty names")
|
||||
|
||||
mnames <<- gsub('-', '_', names(env$bst_evaluation), fixed = TRUE)
|
||||
mnames <<- gsub('-', '_', names(env$bst_evaluation))
|
||||
if (!is.null(env$bst_evaluation_err))
|
||||
mnames <<- c(paste0(mnames, '_mean'), paste0(mnames, '_std'))
|
||||
}
|
||||
@@ -185,7 +185,7 @@ cb.reset.parameters <- function(new_params) {
|
||||
|
||||
if (typeof(new_params) != "list")
|
||||
stop("'new_params' must be a list")
|
||||
pnames <- gsub(".", "_", names(new_params), fixed = TRUE)
|
||||
pnames <- gsub("\\.", "_", names(new_params))
|
||||
nrounds <- NULL
|
||||
|
||||
# run some checks in the beginning
|
||||
@@ -300,9 +300,9 @@ cb.early.stop <- function(stopping_rounds, maximize = FALSE,
|
||||
if (length(env$bst_evaluation) == 0)
|
||||
stop("For early stopping, watchlist must have at least one element")
|
||||
|
||||
eval_names <- gsub('-', '_', names(env$bst_evaluation), fixed = TRUE)
|
||||
eval_names <- gsub('-', '_', names(env$bst_evaluation))
|
||||
if (!is.null(metric_name)) {
|
||||
metric_idx <<- which(gsub('-', '_', metric_name, fixed = TRUE) == eval_names)
|
||||
metric_idx <<- which(gsub('-', '_', metric_name) == eval_names)
|
||||
if (length(metric_idx) == 0)
|
||||
stop("'metric_name' for early stopping is not one of the following:\n",
|
||||
paste(eval_names, collapse = ' '), '\n')
|
||||
@@ -319,7 +319,7 @@ cb.early.stop <- function(stopping_rounds, maximize = FALSE,
|
||||
|
||||
# maximize is usually NULL when not set in xgb.train and built-in metrics
|
||||
if (is.null(maximize))
|
||||
maximize <<- grepl('(_auc|_map|_ndcg|_pre)', metric_name)
|
||||
maximize <<- grepl('(_auc|_map|_ndcg)', metric_name)
|
||||
|
||||
if (verbose && NVL(env$rank, 0) == 0)
|
||||
cat("Will train until ", metric_name, " hasn't improved in ",
|
||||
@@ -544,11 +544,9 @@ cb.cv.predict <- function(save_models = FALSE) {
|
||||
#'
|
||||
#' @return
|
||||
#' Results are stored in the \code{coefs} element of the closure.
|
||||
#' The \code{\link{xgb.gblinear.history}} convenience function provides an easy
|
||||
#' way to access it.
|
||||
#' The \code{\link{xgb.gblinear.history}} convenience function provides an easy way to access it.
|
||||
#' With \code{xgb.train}, it is either a dense of a sparse matrix.
|
||||
#' While with \code{xgb.cv}, it is a list (an element per each fold) of such
|
||||
#' matrices.
|
||||
#' While with \code{xgb.cv}, it is a list (an element per each fold) of such matrices.
|
||||
#'
|
||||
#' @seealso
|
||||
#' \code{\link{callbacks}}, \code{\link{xgb.gblinear.history}}.
|
||||
@@ -560,7 +558,7 @@ cb.cv.predict <- function(save_models = FALSE) {
|
||||
#' # without considering the 2nd order interactions:
|
||||
#' x <- model.matrix(Species ~ .^2, iris)[,-1]
|
||||
#' colnames(x)
|
||||
#' dtrain <- xgb.DMatrix(scale(x), label = 1*(iris$Species == "versicolor"), nthread = 2)
|
||||
#' dtrain <- xgb.DMatrix(scale(x), label = 1*(iris$Species == "versicolor"))
|
||||
#' param <- list(booster = "gblinear", objective = "reg:logistic", eval_metric = "auc",
|
||||
#' lambda = 0.0003, alpha = 0.0003, nthread = 2)
|
||||
#' # For 'shotgun', which is a default linear updater, using high eta values may result in
|
||||
@@ -585,19 +583,19 @@ cb.cv.predict <- function(save_models = FALSE) {
|
||||
#'
|
||||
#' # For xgb.cv:
|
||||
#' bst <- xgb.cv(param, dtrain, nfold = 5, nrounds = 100, eta = 0.8,
|
||||
#' callbacks = list(cb.gblinear.history()))
|
||||
#' callbacks = list(cb.gblinear.history()))
|
||||
#' # coefficients in the CV fold #3
|
||||
#' matplot(xgb.gblinear.history(bst)[[3]], type = 'l')
|
||||
#'
|
||||
#'
|
||||
#' #### Multiclass classification:
|
||||
#' #
|
||||
#' dtrain <- xgb.DMatrix(scale(x), label = as.numeric(iris$Species) - 1, nthread = 1)
|
||||
#' dtrain <- xgb.DMatrix(scale(x), label = as.numeric(iris$Species) - 1)
|
||||
#' param <- list(booster = "gblinear", objective = "multi:softprob", num_class = 3,
|
||||
#' lambda = 0.0003, alpha = 0.0003, nthread = 1)
|
||||
#' lambda = 0.0003, alpha = 0.0003, nthread = 2)
|
||||
#' # For the default linear updater 'shotgun' it sometimes is helpful
|
||||
#' # to use smaller eta to reduce instability
|
||||
#' bst <- xgb.train(param, dtrain, list(tr=dtrain), nrounds = 50, eta = 0.5,
|
||||
#' bst <- xgb.train(param, dtrain, list(tr=dtrain), nrounds = 70, eta = 0.5,
|
||||
#' callbacks = list(cb.gblinear.history()))
|
||||
#' # Will plot the coefficient paths separately for each class:
|
||||
#' matplot(xgb.gblinear.history(bst, class_index = 0), type = 'l')
|
||||
@@ -611,15 +609,13 @@ cb.cv.predict <- function(save_models = FALSE) {
|
||||
#' matplot(xgb.gblinear.history(bst, class_index = 0)[[1]], type = 'l')
|
||||
#'
|
||||
#' @export
|
||||
cb.gblinear.history <- function(sparse = FALSE) {
|
||||
cb.gblinear.history <- function(sparse=FALSE) {
|
||||
coefs <- NULL
|
||||
|
||||
init <- function(env) {
|
||||
# xgb.train(): bst will be present
|
||||
# xgb.cv(): bst_folds will be present
|
||||
if (is.null(env$bst) && is.null(env$bst_folds)) {
|
||||
stop("Parent frame has neither 'bst' nor 'bst_folds'")
|
||||
}
|
||||
if (!is.null(env$bst)) { # xgb.train:
|
||||
} else if (!is.null(env$bst_folds)) { # xgb.cv:
|
||||
} else stop("Parent frame has neither 'bst' nor 'bst_folds'")
|
||||
}
|
||||
|
||||
# convert from list to (sparse) matrix
|
||||
|
||||
@@ -38,11 +38,11 @@ check.booster.params <- function(params, ...) {
|
||||
stop("params must be a list")
|
||||
|
||||
# in R interface, allow for '.' instead of '_' in parameter names
|
||||
names(params) <- gsub(".", "_", names(params), fixed = TRUE)
|
||||
names(params) <- gsub("\\.", "_", names(params))
|
||||
|
||||
# merge parameters from the params and the dots-expansion
|
||||
dot_params <- list(...)
|
||||
names(dot_params) <- gsub(".", "_", names(dot_params), fixed = TRUE)
|
||||
names(dot_params) <- gsub("\\.", "_", names(dot_params))
|
||||
if (length(intersect(names(params),
|
||||
names(dot_params))) > 0)
|
||||
stop("Same parameters in 'params' and in the call are not allowed. Please check your 'params' list.")
|
||||
@@ -82,7 +82,7 @@ check.booster.params <- function(params, ...) {
|
||||
|
||||
# interaction constraints parser (convert from list of column indices to string)
|
||||
if (!is.null(params[['interaction_constraints']]) &&
|
||||
typeof(params[['interaction_constraints']]) != "character") {
|
||||
typeof(params[['interaction_constraints']]) != "character"){
|
||||
# check input class
|
||||
if (!identical(class(params[['interaction_constraints']]), 'list')) stop('interaction_constraints should be class list')
|
||||
if (!all(unique(sapply(params[['interaction_constraints']], class)) %in% c('numeric', 'integer'))) {
|
||||
@@ -251,7 +251,8 @@ generate.cv.folds <- function(nfold, nrows, stratified, label, params) {
|
||||
# Creates CV folds stratified by the values of y.
|
||||
# It was borrowed from caret::createFolds and simplified
|
||||
# by always returning an unnamed list of fold indices.
|
||||
xgb.createFolds <- function(y, k = 10) {
|
||||
xgb.createFolds <- function(y, k = 10)
|
||||
{
|
||||
if (is.numeric(y)) {
|
||||
## Group the numeric data based on their magnitudes
|
||||
## and sample within those groups.
|
||||
|
||||
@@ -162,11 +162,7 @@ xgb.Booster.complete <- function(object, saveraw = TRUE) {
|
||||
#' Predicted values based on either xgboost model or model handle object.
|
||||
#'
|
||||
#' @param object Object of class \code{xgb.Booster} or \code{xgb.Booster.handle}
|
||||
#' @param newdata takes \code{matrix}, \code{dgCMatrix}, \code{dgRMatrix}, \code{dsparseVector},
|
||||
#' local data file or \code{xgb.DMatrix}.
|
||||
#'
|
||||
#' For single-row predictions on sparse data, it's recommended to use CSR format. If passing
|
||||
#' a sparse vector, it will take it as a row vector.
|
||||
#' @param newdata takes \code{matrix}, \code{dgCMatrix}, local data file or \code{xgb.DMatrix}.
|
||||
#' @param missing Missing is only used when input is dense matrix. Pick a float value that represents
|
||||
#' missing values in data (e.g., sometimes 0 or some other extreme value is used).
|
||||
#' @param outputmargin whether the prediction should be returned in the for of original untransformed
|
||||
@@ -184,7 +180,7 @@ xgb.Booster.complete <- function(object, saveraw = TRUE) {
|
||||
#' training predicting will perform dropout.
|
||||
#' @param iterationrange Specifies which layer of trees are used in prediction. For
|
||||
#' example, if a random forest is trained with 100 rounds. Specifying
|
||||
#' `iterationrange=(1, 21)`, then only the forests built during [1, 21) (half open set)
|
||||
#' `iteration_range=(1, 21)`, then only the forests built during [1, 21) (half open set)
|
||||
#' rounds are used in this prediction. It's 1-based index just like R vector. When set
|
||||
#' to \code{c(1, 1)} XGBoost will use all trees.
|
||||
#' @param strict_shape Default is \code{FALSE}. When it's set to \code{TRUE}, output
|
||||
@@ -214,10 +210,6 @@ xgb.Booster.complete <- function(object, saveraw = TRUE) {
|
||||
#' Since it quadratically depends on the number of features, it is recommended to perform selection
|
||||
#' of the most important features first. See below about the format of the returned results.
|
||||
#'
|
||||
#' The \code{predict()} method uses as many threads as defined in \code{xgb.Booster} object (all by default).
|
||||
#' If you want to change their number, then assign a new number to \code{nthread} using \code{\link{xgb.parameters<-}}.
|
||||
#' Note also that converting a matrix to \code{\link{xgb.DMatrix}} uses multiple threads too.
|
||||
#'
|
||||
#' @return
|
||||
#' The return type is different depending whether \code{strict_shape} is set to \code{TRUE}. By default,
|
||||
#' for regression or binary classification, it returns a vector of length \code{nrows(newdata)}.
|
||||
@@ -332,9 +324,8 @@ predict.xgb.Booster <- function(object, newdata, missing = NA, outputmargin = FA
|
||||
predleaf = FALSE, predcontrib = FALSE, approxcontrib = FALSE, predinteraction = FALSE,
|
||||
reshape = FALSE, training = FALSE, iterationrange = NULL, strict_shape = FALSE, ...) {
|
||||
object <- xgb.Booster.complete(object, saveraw = FALSE)
|
||||
|
||||
if (!inherits(newdata, "xgb.DMatrix"))
|
||||
newdata <- xgb.DMatrix(newdata, missing = missing, nthread = NVL(object$params[["nthread"]], -1))
|
||||
newdata <- xgb.DMatrix(newdata, missing = missing)
|
||||
if (!is.null(object[["feature_names"]]) &&
|
||||
!is.null(colnames(newdata)) &&
|
||||
!identical(object[["feature_names"]], colnames(newdata)))
|
||||
@@ -406,7 +397,6 @@ predict.xgb.Booster <- function(object, newdata, missing = NA, outputmargin = FA
|
||||
shape <- predts$shape
|
||||
ret <- predts$results
|
||||
|
||||
n_ret <- length(ret)
|
||||
n_row <- nrow(newdata)
|
||||
if (n_row != shape[1]) {
|
||||
stop("Incorrect predict shape.")
|
||||
@@ -415,57 +405,36 @@ predict.xgb.Booster <- function(object, newdata, missing = NA, outputmargin = FA
|
||||
arr <- array(data = ret, dim = rev(shape))
|
||||
|
||||
cnames <- if (!is.null(colnames(newdata))) c(colnames(newdata), "BIAS") else NULL
|
||||
n_groups <- shape[2]
|
||||
|
||||
## Needed regardless of whether strict shape is being used.
|
||||
if (predcontrib) {
|
||||
dimnames(arr) <- list(cnames, NULL, NULL)
|
||||
if (!strict_shape) {
|
||||
arr <- aperm(a = arr, perm = c(2, 3, 1)) # [group, row, col]
|
||||
}
|
||||
} else if (predinteraction) {
|
||||
dimnames(arr) <- list(cnames, cnames, NULL, NULL)
|
||||
}
|
||||
if (strict_shape) {
|
||||
return(arr) # strict shape is calculated by libxgboost uniformly.
|
||||
if (!strict_shape) {
|
||||
arr <- aperm(a = arr, perm = c(3, 4, 1, 2)) # [group, row, col, col]
|
||||
}
|
||||
}
|
||||
|
||||
if (predleaf) {
|
||||
## Predict leaf
|
||||
arr <- if (n_ret == n_row) {
|
||||
matrix(arr, ncol = 1)
|
||||
} else {
|
||||
matrix(arr, nrow = n_row, byrow = TRUE)
|
||||
if (!strict_shape) {
|
||||
n_groups <- shape[2]
|
||||
if (predleaf) {
|
||||
arr <- matrix(arr, nrow = n_row, byrow = TRUE)
|
||||
} else if (predcontrib && n_groups != 1) {
|
||||
arr <- lapply(seq_len(n_groups), function(g) arr[g, , ])
|
||||
} else if (predinteraction && n_groups != 1) {
|
||||
arr <- lapply(seq_len(n_groups), function(g) arr[g, , , ])
|
||||
} else if (!reshape && n_groups != 1) {
|
||||
arr <- ret
|
||||
} else if (reshape && n_groups != 1) {
|
||||
arr <- matrix(arr, ncol = n_groups, byrow = TRUE)
|
||||
}
|
||||
} else if (predcontrib) {
|
||||
## Predict contribution
|
||||
arr <- aperm(a = arr, perm = c(2, 3, 1)) # [group, row, col]
|
||||
arr <- if (n_ret == n_row) {
|
||||
matrix(arr, ncol = 1, dimnames = list(NULL, cnames))
|
||||
} else if (n_groups != 1) {
|
||||
## turns array into list of matrices
|
||||
lapply(seq_len(n_groups), function(g) arr[g, , ])
|
||||
} else {
|
||||
## remove the first axis (group)
|
||||
dn <- dimnames(arr)
|
||||
matrix(arr[1, , ], nrow = dim(arr)[2], ncol = dim(arr)[3], dimnames = c(dn[2], dn[3]))
|
||||
}
|
||||
} else if (predinteraction) {
|
||||
## Predict interaction
|
||||
arr <- aperm(a = arr, perm = c(3, 4, 1, 2)) # [group, row, col, col]
|
||||
arr <- if (n_ret == n_row) {
|
||||
matrix(arr, ncol = 1, dimnames = list(NULL, cnames))
|
||||
} else if (n_groups != 1) {
|
||||
## turns array into list of matrices
|
||||
lapply(seq_len(n_groups), function(g) arr[g, , , ])
|
||||
} else {
|
||||
## remove the first axis (group)
|
||||
arr <- arr[1, , , , drop = FALSE]
|
||||
array(arr, dim = dim(arr)[2:4], dimnames(arr)[2:4])
|
||||
}
|
||||
} else {
|
||||
## Normal prediction
|
||||
arr <- if (reshape && n_groups != 1) {
|
||||
matrix(arr, ncol = n_groups, byrow = TRUE)
|
||||
} else {
|
||||
as.vector(ret)
|
||||
arr <- drop(arr)
|
||||
if (length(dim(arr)) == 1) {
|
||||
arr <- as.vector(arr)
|
||||
} else if (length(dim(arr)) == 2) {
|
||||
arr <- as.matrix(arr)
|
||||
}
|
||||
}
|
||||
return(arr)
|
||||
@@ -634,7 +603,7 @@ xgb.attributes <- function(object) {
|
||||
#' @export
|
||||
xgb.config <- function(object) {
|
||||
handle <- xgb.get.handle(object)
|
||||
.Call(XGBoosterSaveJsonConfig_R, handle)
|
||||
.Call(XGBoosterSaveJsonConfig_R, handle);
|
||||
}
|
||||
|
||||
#' @rdname xgb.config
|
||||
@@ -676,7 +645,7 @@ xgb.config <- function(object) {
|
||||
if (is.null(names(p)) || any(nchar(names(p)) == 0)) {
|
||||
stop("parameter names cannot be empty strings")
|
||||
}
|
||||
names(p) <- gsub(".", "_", names(p), fixed = TRUE)
|
||||
names(p) <- gsub("\\.", "_", names(p))
|
||||
p <- lapply(p, function(x) as.character(x)[1])
|
||||
handle <- xgb.get.handle(object)
|
||||
for (i in seq_along(p)) {
|
||||
|
||||
@@ -4,21 +4,18 @@
|
||||
#' Supported input file formats are either a LIBSVM text file or a binary file that was created previously by
|
||||
#' \code{\link{xgb.DMatrix.save}}).
|
||||
#'
|
||||
#' @param data a \code{matrix} object (either numeric or integer), a \code{dgCMatrix} object,
|
||||
#' a \code{dgRMatrix} object (only when making predictions from a fitted model),
|
||||
#' a \code{dsparseVector} object (only when making predictions from a fitted model, will be
|
||||
#' interpreted as a row vector), or a character string representing a filename.
|
||||
#' @param data a \code{matrix} object (either numeric or integer), a \code{dgCMatrix} object, or a character
|
||||
#' string representing a filename.
|
||||
#' @param info a named list of additional information to store in the \code{xgb.DMatrix} object.
|
||||
#' See \code{\link{setinfo}} for the specific allowed kinds of
|
||||
#' @param missing a float value to represents missing values in data (used only when input is a dense matrix).
|
||||
#' It is useful when a 0 or some other extreme value represents missing values in data.
|
||||
#' @param silent whether to suppress printing an informational message after loading from a file.
|
||||
#' @param nthread Number of threads used for creating DMatrix.
|
||||
#' @param ... the \code{info} data could be passed directly as parameters, without creating an \code{info} list.
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#' xgb.DMatrix.save(dtrain, 'xgb.DMatrix.data')
|
||||
#' dtrain <- xgb.DMatrix('xgb.DMatrix.data')
|
||||
#' if (file.exists('xgb.DMatrix.data')) file.remove('xgb.DMatrix.data')
|
||||
@@ -35,47 +32,13 @@ xgb.DMatrix <- function(data, info = list(), missing = NA, silent = FALSE, nthre
|
||||
handle <- .Call(XGDMatrixCreateFromMat_R, data, missing, as.integer(NVL(nthread, -1)))
|
||||
cnames <- colnames(data)
|
||||
} else if (inherits(data, "dgCMatrix")) {
|
||||
handle <- .Call(
|
||||
XGDMatrixCreateFromCSC_R,
|
||||
data@p,
|
||||
data@i,
|
||||
data@x,
|
||||
nrow(data),
|
||||
missing,
|
||||
as.integer(NVL(nthread, -1))
|
||||
)
|
||||
handle <- .Call(XGDMatrixCreateFromCSC_R, data@p, data@i, data@x, nrow(data))
|
||||
cnames <- colnames(data)
|
||||
} else if (inherits(data, "dgRMatrix")) {
|
||||
handle <- .Call(
|
||||
XGDMatrixCreateFromCSR_R,
|
||||
data@p,
|
||||
data@j,
|
||||
data@x,
|
||||
ncol(data),
|
||||
missing,
|
||||
as.integer(NVL(nthread, -1))
|
||||
)
|
||||
cnames <- colnames(data)
|
||||
} else if (inherits(data, "dsparseVector")) {
|
||||
indptr <- c(0L, as.integer(length(data@i)))
|
||||
ind <- as.integer(data@i) - 1L
|
||||
handle <- .Call(
|
||||
XGDMatrixCreateFromCSR_R,
|
||||
indptr,
|
||||
ind,
|
||||
data@x,
|
||||
length(data),
|
||||
missing,
|
||||
as.integer(NVL(nthread, -1))
|
||||
)
|
||||
} else {
|
||||
stop("xgb.DMatrix does not support construction from ", typeof(data))
|
||||
}
|
||||
dmat <- handle
|
||||
attributes(dmat) <- list(class = "xgb.DMatrix")
|
||||
if (!is.null(cnames)) {
|
||||
setinfo(dmat, "feature_name", cnames)
|
||||
}
|
||||
attributes(dmat) <- list(.Dimnames = list(NULL, cnames), class = "xgb.DMatrix")
|
||||
|
||||
info <- append(info, list(...))
|
||||
for (i in seq_along(info)) {
|
||||
@@ -94,7 +57,7 @@ xgb.get.DMatrix <- function(data, label = NULL, missing = NA, weight = NULL, nth
|
||||
stop("label must be provided when data is a matrix")
|
||||
}
|
||||
dtrain <- xgb.DMatrix(data, label = label, missing = missing, nthread = nthread)
|
||||
if (!is.null(weight)) {
|
||||
if (!is.null(weight)){
|
||||
setinfo(dtrain, "weight", weight)
|
||||
}
|
||||
} else {
|
||||
@@ -128,7 +91,7 @@ xgb.get.DMatrix <- function(data, label = NULL, missing = NA, weight = NULL, nth
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' train <- agaricus.train
|
||||
#' dtrain <- xgb.DMatrix(train$data, label=train$label, nthread = 2)
|
||||
#' dtrain <- xgb.DMatrix(train$data, label=train$label)
|
||||
#'
|
||||
#' stopifnot(nrow(dtrain) == nrow(train$data))
|
||||
#' stopifnot(ncol(dtrain) == ncol(train$data))
|
||||
@@ -156,7 +119,7 @@ dim.xgb.DMatrix <- function(x) {
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' train <- agaricus.train
|
||||
#' dtrain <- xgb.DMatrix(train$data, label=train$label, nthread = 2)
|
||||
#' dtrain <- xgb.DMatrix(train$data, label=train$label)
|
||||
#' dimnames(dtrain)
|
||||
#' colnames(dtrain)
|
||||
#' colnames(dtrain) <- make.names(1:ncol(train$data))
|
||||
@@ -165,9 +128,7 @@ dim.xgb.DMatrix <- function(x) {
|
||||
#' @rdname dimnames.xgb.DMatrix
|
||||
#' @export
|
||||
dimnames.xgb.DMatrix <- function(x) {
|
||||
fn <- getinfo(x, "feature_name")
|
||||
## row names is null.
|
||||
list(NULL, fn)
|
||||
attr(x, '.Dimnames')
|
||||
}
|
||||
|
||||
#' @rdname dimnames.xgb.DMatrix
|
||||
@@ -178,13 +139,13 @@ dimnames.xgb.DMatrix <- function(x) {
|
||||
if (!is.null(value[[1L]]))
|
||||
stop("xgb.DMatrix does not have rownames")
|
||||
if (is.null(value[[2]])) {
|
||||
setinfo(x, "feature_name", NULL)
|
||||
attr(x, '.Dimnames') <- NULL
|
||||
return(x)
|
||||
}
|
||||
if (ncol(x) != length(value[[2]])) {
|
||||
stop("can't assign ", length(value[[2]]), " colnames to a ", ncol(x), " column xgb.DMatrix")
|
||||
}
|
||||
setinfo(x, "feature_name", value[[2]])
|
||||
if (ncol(x) != length(value[[2]]))
|
||||
stop("can't assign ", length(value[[2]]), " colnames to a ",
|
||||
ncol(x), " column xgb.DMatrix")
|
||||
attr(x, '.Dimnames') <- value
|
||||
x
|
||||
}
|
||||
|
||||
@@ -211,7 +172,7 @@ dimnames.xgb.DMatrix <- function(x) {
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#'
|
||||
#' labels <- getinfo(dtrain, 'label')
|
||||
#' setinfo(dtrain, 'label', 1-labels)
|
||||
@@ -226,17 +187,13 @@ getinfo <- function(object, ...) UseMethod("getinfo")
|
||||
#' @export
|
||||
getinfo.xgb.DMatrix <- function(object, name, ...) {
|
||||
if (typeof(name) != "character" ||
|
||||
length(name) != 1 ||
|
||||
!name %in% c('label', 'weight', 'base_margin', 'nrow',
|
||||
'label_lower_bound', 'label_upper_bound', "feature_type", "feature_name")) {
|
||||
stop(
|
||||
"getinfo: name must be one of the following\n",
|
||||
" 'label', 'weight', 'base_margin', 'nrow', 'label_lower_bound', 'label_upper_bound', 'feature_type', 'feature_name'"
|
||||
)
|
||||
length(name) != 1 ||
|
||||
!name %in% c('label', 'weight', 'base_margin', 'nrow',
|
||||
'label_lower_bound', 'label_upper_bound')) {
|
||||
stop("getinfo: name must be one of the following\n",
|
||||
" 'label', 'weight', 'base_margin', 'nrow', 'label_lower_bound', 'label_upper_bound'")
|
||||
}
|
||||
if (name == "feature_name" || name == "feature_type") {
|
||||
ret <- .Call(XGDMatrixGetStrFeatureInfo_R, object, name)
|
||||
} else if (name != "nrow") {
|
||||
if (name != "nrow"){
|
||||
ret <- .Call(XGDMatrixGetInfo_R, object, name)
|
||||
} else {
|
||||
ret <- nrow(object)
|
||||
@@ -267,7 +224,7 @@ getinfo.xgb.DMatrix <- function(object, name, ...) {
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#'
|
||||
#' labels <- getinfo(dtrain, 'label')
|
||||
#' setinfo(dtrain, 'label', 1-labels)
|
||||
@@ -314,38 +271,8 @@ setinfo.xgb.DMatrix <- function(object, name, info, ...) {
|
||||
.Call(XGDMatrixSetInfo_R, object, name, as.integer(info))
|
||||
return(TRUE)
|
||||
}
|
||||
if (name == "feature_weights") {
|
||||
if (length(info) != ncol(object)) {
|
||||
stop("The number of feature weights must equal to the number of columns in the input data")
|
||||
}
|
||||
.Call(XGDMatrixSetInfo_R, object, name, as.numeric(info))
|
||||
return(TRUE)
|
||||
}
|
||||
|
||||
set_feat_info <- function(name) {
|
||||
msg <- sprintf(
|
||||
"The number of %s must equal to the number of columns in the input data. %s vs. %s",
|
||||
name,
|
||||
length(info),
|
||||
ncol(object)
|
||||
)
|
||||
if (!is.null(info)) {
|
||||
info <- as.list(info)
|
||||
if (length(info) != ncol(object)) {
|
||||
stop(msg)
|
||||
}
|
||||
}
|
||||
.Call(XGDMatrixSetStrFeatureInfo_R, object, name, info)
|
||||
}
|
||||
if (name == "feature_name") {
|
||||
set_feat_info("feature_name")
|
||||
return(TRUE)
|
||||
}
|
||||
if (name == "feature_type") {
|
||||
set_feat_info("feature_type")
|
||||
return(TRUE)
|
||||
}
|
||||
stop("setinfo: unknown info name ", name)
|
||||
return(FALSE)
|
||||
}
|
||||
|
||||
|
||||
@@ -362,7 +289,7 @@ setinfo.xgb.DMatrix <- function(object, name, info, ...) {
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#'
|
||||
#' dsub <- slice(dtrain, 1:42)
|
||||
#' labels1 <- getinfo(dsub, 'label')
|
||||
@@ -418,7 +345,7 @@ slice.xgb.DMatrix <- function(object, idxset, ...) {
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#'
|
||||
#' dtrain
|
||||
#' print(dtrain, verbose=TRUE)
|
||||
@@ -435,7 +362,7 @@ print.xgb.DMatrix <- function(x, verbose = FALSE, ...) {
|
||||
cat(infos)
|
||||
cnames <- colnames(x)
|
||||
cat(' colnames:')
|
||||
if (verbose && !is.null(cnames)) {
|
||||
if (verbose & !is.null(cnames)) {
|
||||
cat("\n'")
|
||||
cat(cnames, sep = "','")
|
||||
cat("'")
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#' xgb.DMatrix.save(dtrain, 'xgb.DMatrix.data')
|
||||
#' dtrain <- xgb.DMatrix('xgb.DMatrix.data')
|
||||
#' if (file.exists('xgb.DMatrix.data')) file.remove('xgb.DMatrix.data')
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#'
|
||||
#' International Workshop on Data Mining for Online Advertising (ADKDD) - August 24, 2014
|
||||
#'
|
||||
#' \url{https://research.facebook.com/publications/practical-lessons-from-predicting-clicks-on-ads-at-facebook/}.
|
||||
#' \url{https://research.fb.com/publications/practical-lessons-from-predicting-clicks-on-ads-at-facebook/}.
|
||||
#'
|
||||
#' Extract explaining the method:
|
||||
#'
|
||||
@@ -48,8 +48,8 @@
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' data(agaricus.test, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtest <- with(agaricus.test, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#' dtest <- with(agaricus.test, xgb.DMatrix(data, label = label))
|
||||
#'
|
||||
#' param <- list(max_depth=2, eta=1, silent=1, objective='binary:logistic')
|
||||
#' nrounds = 4
|
||||
@@ -65,12 +65,8 @@
|
||||
#' new.features.test <- xgb.create.features(model = bst, agaricus.test$data)
|
||||
#'
|
||||
#' # learning with new features
|
||||
#' new.dtrain <- xgb.DMatrix(
|
||||
#' data = new.features.train, label = agaricus.train$label, nthread = 2
|
||||
#' )
|
||||
#' new.dtest <- xgb.DMatrix(
|
||||
#' data = new.features.test, label = agaricus.test$label, nthread = 2
|
||||
#' )
|
||||
#' new.dtrain <- xgb.DMatrix(data = new.features.train, label = agaricus.train$label)
|
||||
#' new.dtest <- xgb.DMatrix(data = new.features.test, label = agaricus.test$label)
|
||||
#' watchlist <- list(train = new.dtrain)
|
||||
#' bst <- xgb.train(params = param, data = new.dtrain, nrounds = nrounds, nthread = 2)
|
||||
#'
|
||||
@@ -83,7 +79,7 @@
|
||||
#' accuracy.after, "!\n"))
|
||||
#'
|
||||
#' @export
|
||||
xgb.create.features <- function(model, data, ...) {
|
||||
xgb.create.features <- function(model, data, ...){
|
||||
check.deprecation(...)
|
||||
pred_with_leaf <- predict(model, data, predleaf = TRUE)
|
||||
cols <- lapply(as.data.frame(pred_with_leaf), factor)
|
||||
|
||||
@@ -75,11 +75,9 @@
|
||||
#' @details
|
||||
#' The original sample is randomly partitioned into \code{nfold} equal size subsamples.
|
||||
#'
|
||||
#' Of the \code{nfold} subsamples, a single subsample is retained as the validation data for testing the model,
|
||||
#' and the remaining \code{nfold - 1} subsamples are used as training data.
|
||||
#' Of the \code{nfold} subsamples, a single subsample is retained as the validation data for testing the model, and the remaining \code{nfold - 1} subsamples are used as training data.
|
||||
#'
|
||||
#' The cross-validation process is then repeated \code{nrounds} times, with each of the
|
||||
#' \code{nfold} subsamples used exactly once as the validation data.
|
||||
#' The cross-validation process is then repeated \code{nrounds} times, with each of the \code{nfold} subsamples used exactly once as the validation data.
|
||||
#'
|
||||
#' All observations are used for both training and validation.
|
||||
#'
|
||||
@@ -112,17 +110,17 @@
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#' cv <- xgb.cv(data = dtrain, nrounds = 3, nthread = 2, nfold = 5, metrics = list("rmse","auc"),
|
||||
#' max_depth = 3, eta = 1, objective = "binary:logistic")
|
||||
#' max_depth = 3, eta = 1, objective = "binary:logistic")
|
||||
#' print(cv)
|
||||
#' print(cv, verbose=TRUE)
|
||||
#'
|
||||
#' @export
|
||||
xgb.cv <- function(params = list(), data, nrounds, nfold, label = NULL, missing = NA,
|
||||
prediction = FALSE, showsd = TRUE, metrics = list(),
|
||||
xgb.cv <- function(params=list(), data, nrounds, nfold, label = NULL, missing = NA,
|
||||
prediction = FALSE, showsd = TRUE, metrics=list(),
|
||||
obj = NULL, feval = NULL, stratified = TRUE, folds = NULL, train_folds = NULL,
|
||||
verbose = TRUE, print_every_n = 1L,
|
||||
verbose = TRUE, print_every_n=1L,
|
||||
early_stopping_rounds = NULL, maximize = NULL, callbacks = list(), ...) {
|
||||
|
||||
check.deprecation(...)
|
||||
@@ -194,7 +192,7 @@ xgb.cv <- function(params = list(), data, nrounds, nfold, label = NULL, missing
|
||||
|
||||
# create the booster-folds
|
||||
# train_folds
|
||||
dall <- xgb.get.DMatrix(data, label, missing, nthread = params$nthread)
|
||||
dall <- xgb.get.DMatrix(data, label, missing)
|
||||
bst_folds <- lapply(seq_along(folds), function(k) {
|
||||
dtest <- slice(dall, folds[[k]])
|
||||
# code originally contributed by @RolandASc on stackoverflow
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#' @param fname the name of the text file where to save the model text dump.
|
||||
#' If not provided or set to \code{NULL}, the model is returned as a \code{character} vector.
|
||||
#' @param fmap feature map file representing feature types.
|
||||
#' Detailed description could be found at
|
||||
#' \url{https://github.com/dmlc/xgboost/wiki/Binary-Classification#dump-model}.
|
||||
#' See demo/ for walkthrough example in R, and
|
||||
#' \url{https://github.com/dmlc/xgboost/blob/master/demo/data/featmap.txt}
|
||||
#' for example Format.
|
||||
@@ -38,7 +40,7 @@
|
||||
#' cat(xgb.dump(bst, with_stats = TRUE, dump_format='json'))
|
||||
#'
|
||||
#' @export
|
||||
xgb.dump <- function(model, fname = NULL, fmap = "", with_stats = FALSE,
|
||||
xgb.dump <- function(model, fname = NULL, fmap = "", with_stats=FALSE,
|
||||
dump_format = c("text", "json"), ...) {
|
||||
check.deprecation(...)
|
||||
dump_format <- match.arg(dump_format)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#' @rdname xgb.plot.importance
|
||||
#' @export
|
||||
xgb.ggplot.importance <- function(importance_matrix = NULL, top_n = NULL, measure = NULL,
|
||||
rel_to_first = FALSE, n_clusters = seq_len(10), ...) {
|
||||
rel_to_first = FALSE, n_clusters = c(1:10), ...) {
|
||||
|
||||
importance_matrix <- xgb.plot.importance(importance_matrix, top_n = top_n, measure = measure,
|
||||
rel_to_first = rel_to_first, plot = FALSE, ...)
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
#'
|
||||
#' @export
|
||||
xgb.importance <- function(feature_names = NULL, model = NULL, trees = NULL,
|
||||
data = NULL, label = NULL, target = NULL) {
|
||||
data = NULL, label = NULL, target = NULL){
|
||||
|
||||
if (!(is.null(data) && is.null(label) && is.null(target)))
|
||||
warning("xgb.importance: parameters 'data', 'label' and 'target' are deprecated")
|
||||
@@ -104,11 +104,7 @@ xgb.importance <- function(feature_names = NULL, model = NULL, trees = NULL,
|
||||
XGBoosterFeatureScore_R, model$handle, jsonlite::toJSON(args, auto_unbox = TRUE, null = "null")
|
||||
)
|
||||
names(results) <- c("features", "shape", "weight")
|
||||
if (length(results$shape) == 2) {
|
||||
n_classes <- results$shape[2]
|
||||
} else {
|
||||
n_classes <- 0
|
||||
}
|
||||
n_classes <- if (length(results$shape) == 2) { results$shape[2] } else { 0 }
|
||||
importance <- if (n_classes == 0) {
|
||||
data.table(Feature = results$features, Weight = results$weight)[order(-abs(Weight))]
|
||||
} else {
|
||||
@@ -119,14 +115,14 @@ xgb.importance <- function(feature_names = NULL, model = NULL, trees = NULL,
|
||||
} else {
|
||||
concatenated <- list()
|
||||
output_names <- vector()
|
||||
for (importance_type in c("weight", "total_gain", "total_cover")) {
|
||||
args <- list(importance_type = importance_type, feature_names = feature_names, tree_idx = trees)
|
||||
for (importance_type in c("weight", "gain", "cover")) {
|
||||
args <- list(importance_type = importance_type, feature_names = feature_names)
|
||||
results <- .Call(
|
||||
XGBoosterFeatureScore_R, model$handle, jsonlite::toJSON(args, auto_unbox = TRUE, null = "null")
|
||||
)
|
||||
names(results) <- c("features", "shape", importance_type)
|
||||
concatenated[
|
||||
switch(importance_type, "weight" = "Frequency", "total_gain" = "Gain", "total_cover" = "Cover")
|
||||
switch(importance_type, "weight" = "Frequency", "gain" = "Gain", "cover" = "Cover")
|
||||
] <- results[importance_type]
|
||||
output_names <- results$features
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#' @param modelfile the name of the binary input file.
|
||||
#'
|
||||
#' @details
|
||||
#' The input file is expected to contain a model saved in an xgboost model format
|
||||
#' The input file is expected to contain a model saved in an xgboost-internal binary format
|
||||
#' using either \code{\link{xgb.save}} or \code{\link{cb.save.model}} in R, or using some
|
||||
#' appropriate methods from other xgboost interfaces. E.g., a model trained in Python and
|
||||
#' saved from there in xgboost format, could be loaded from R.
|
||||
@@ -38,13 +38,6 @@ xgb.load <- function(modelfile) {
|
||||
handle <- xgb.Booster.handle(modelfile = modelfile)
|
||||
# re-use modelfile if it is raw so we do not need to serialize
|
||||
if (typeof(modelfile) == "raw") {
|
||||
warning(
|
||||
paste(
|
||||
"The support for loading raw booster with `xgb.load` will be ",
|
||||
"discontinued in upcoming release. Use `xgb.load.raw` or",
|
||||
" `xgb.unserialize` instead. "
|
||||
)
|
||||
)
|
||||
bst <- xgb.handleToBooster(handle, modelfile)
|
||||
} else {
|
||||
bst <- xgb.handleToBooster(handle, NULL)
|
||||
|
||||
@@ -3,21 +3,12 @@
|
||||
#' User can generate raw memory buffer by calling xgb.save.raw
|
||||
#'
|
||||
#' @param buffer the buffer returned by xgb.save.raw
|
||||
#' @param as_booster Return the loaded model as xgb.Booster instead of xgb.Booster.handle.
|
||||
#'
|
||||
#' @export
|
||||
xgb.load.raw <- function(buffer, as_booster = FALSE) {
|
||||
xgb.load.raw <- function(buffer) {
|
||||
cachelist <- list()
|
||||
handle <- .Call(XGBoosterCreate_R, cachelist)
|
||||
.Call(XGBoosterLoadModelFromRaw_R, handle, buffer)
|
||||
class(handle) <- "xgb.Booster.handle"
|
||||
|
||||
if (as_booster) {
|
||||
booster <- list(handle = handle, raw = NULL)
|
||||
class(booster) <- "xgb.Booster"
|
||||
booster <- xgb.Booster.complete(booster, saveraw = TRUE)
|
||||
return(booster)
|
||||
} else {
|
||||
return (handle)
|
||||
}
|
||||
return (handle)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
#'
|
||||
#' @export
|
||||
xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
trees = NULL, use_int_id = FALSE, ...) {
|
||||
trees = NULL, use_int_id = FALSE, ...){
|
||||
check.deprecation(...)
|
||||
|
||||
if (!inherits(model, "xgb.Booster") && !is.character(text)) {
|
||||
@@ -82,12 +82,12 @@ xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
stop("trees: must be a vector of integers.")
|
||||
}
|
||||
|
||||
if (is.null(text)) {
|
||||
if (is.null(text)){
|
||||
text <- xgb.dump(model = model, with_stats = TRUE)
|
||||
}
|
||||
|
||||
if (length(text) < 2 ||
|
||||
sum(grepl('leaf=(\\d+)', text)) < 1) {
|
||||
sum(grepl('yes=(\\d+),no=(\\d+)', text)) < 1) {
|
||||
stop("Non-tree model detected! This function can only be used with tree models.")
|
||||
}
|
||||
|
||||
@@ -116,28 +116,16 @@ xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
branch_rx <- paste0("f(\\d+)<(", anynumber_regex, ")\\] yes=(\\d+),no=(\\d+),missing=(\\d+),",
|
||||
"gain=(", anynumber_regex, "),cover=(", anynumber_regex, ")")
|
||||
branch_cols <- c("Feature", "Split", "Yes", "No", "Missing", "Quality", "Cover")
|
||||
td[
|
||||
isLeaf == FALSE,
|
||||
(branch_cols) := {
|
||||
matches <- regmatches(t, regexec(branch_rx, t))
|
||||
# skip some indices with spurious capture groups from anynumber_regex
|
||||
xtr <- do.call(rbind, matches)[, c(2, 3, 5, 6, 7, 8, 10), drop = FALSE]
|
||||
xtr[, 3:5] <- add.tree.id(xtr[, 3:5], Tree)
|
||||
if (length(xtr) == 0) {
|
||||
as.data.table(
|
||||
list(Feature = "NA", Split = "NA", Yes = "NA", No = "NA", Missing = "NA", Quality = "NA", Cover = "NA")
|
||||
)
|
||||
} else {
|
||||
as.data.table(xtr)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
td[isLeaf == FALSE,
|
||||
(branch_cols) := {
|
||||
matches <- regmatches(t, regexec(branch_rx, t))
|
||||
# skip some indices with spurious capture groups from anynumber_regex
|
||||
xtr <- do.call(rbind, matches)[, c(2, 3, 5, 6, 7, 8, 10), drop = FALSE]
|
||||
xtr[, 3:5] <- add.tree.id(xtr[, 3:5], Tree)
|
||||
as.data.table(xtr)
|
||||
}]
|
||||
# assign feature_names when available
|
||||
is_stump <- function() {
|
||||
return(length(td$Feature) == 1 && is.na(td$Feature))
|
||||
}
|
||||
if (!is.null(feature_names) && !is_stump()) {
|
||||
if (!is.null(feature_names)) {
|
||||
if (length(feature_names) <= max(as.numeric(td$Feature), na.rm = TRUE))
|
||||
stop("feature_names has less elements than there are features used in the model")
|
||||
td[isLeaf == FALSE, Feature := feature_names[as.numeric(Feature) + 1]]
|
||||
@@ -146,18 +134,12 @@ xgb.model.dt.tree <- function(feature_names = NULL, model = NULL, text = NULL,
|
||||
# parse leaf lines
|
||||
leaf_rx <- paste0("leaf=(", anynumber_regex, "),cover=(", anynumber_regex, ")")
|
||||
leaf_cols <- c("Feature", "Quality", "Cover")
|
||||
td[
|
||||
isLeaf == TRUE,
|
||||
(leaf_cols) := {
|
||||
matches <- regmatches(t, regexec(leaf_rx, t))
|
||||
xtr <- do.call(rbind, matches)[, c(2, 4)]
|
||||
if (length(xtr) == 2) {
|
||||
c("Leaf", as.data.table(xtr[1]), as.data.table(xtr[2]))
|
||||
} else {
|
||||
c("Leaf", as.data.table(xtr))
|
||||
}
|
||||
}
|
||||
]
|
||||
td[isLeaf == TRUE,
|
||||
(leaf_cols) := {
|
||||
matches <- regmatches(t, regexec(leaf_rx, t))
|
||||
xtr <- do.call(rbind, matches)[, c(2, 4)]
|
||||
c("Leaf", as.data.table(xtr))
|
||||
}]
|
||||
|
||||
# convert some columns to numeric
|
||||
numeric_cols <- c("Split", "Quality", "Cover")
|
||||
|
||||
@@ -102,9 +102,7 @@ xgb.plot.importance <- function(importance_matrix = NULL, top_n = NULL, measure
|
||||
original_mar <- par()$mar
|
||||
|
||||
# reset margins so this function doesn't have side effects
|
||||
on.exit({
|
||||
par(mar = original_mar)
|
||||
})
|
||||
on.exit({par(mar = original_mar)})
|
||||
|
||||
mar <- original_mar
|
||||
if (!is.null(left_margin))
|
||||
|
||||
@@ -61,10 +61,7 @@
|
||||
#'
|
||||
#' @export
|
||||
xgb.plot.multi.trees <- function(model, feature_names = NULL, features_keep = 5, plot_width = NULL, plot_height = NULL,
|
||||
render = TRUE, ...) {
|
||||
if (!requireNamespace("DiagrammeR", quietly = TRUE)) {
|
||||
stop("DiagrammeR is required for xgb.plot.multi.trees")
|
||||
}
|
||||
render = TRUE, ...){
|
||||
check.deprecation(...)
|
||||
tree.matrix <- xgb.model.dt.tree(feature_names = feature_names, model = model)
|
||||
|
||||
@@ -97,9 +94,9 @@ xgb.plot.multi.trees <- function(model, feature_names = NULL, features_keep = 5,
|
||||
, by = .(abs.node.position, Feature)
|
||||
][, .(Text = paste0(
|
||||
paste0(
|
||||
Feature[seq_len(min(length(Feature), features_keep))],
|
||||
Feature[1:min(length(Feature), features_keep)],
|
||||
" (",
|
||||
format(Quality[seq_len(min(length(Quality), features_keep))], digits = 5),
|
||||
format(Quality[1:min(length(Quality), features_keep)], digits = 5),
|
||||
")"
|
||||
),
|
||||
collapse = "\n"
|
||||
|
||||
@@ -143,7 +143,7 @@ xgb.plot.shap <- function(data, shap_contrib = NULL, features = NULL, top_n = 1,
|
||||
y <- shap_contrib[, f][ord]
|
||||
x_lim <- range(x, na.rm = TRUE)
|
||||
y_lim <- range(y, na.rm = TRUE)
|
||||
do_na <- plot_NA && anyNA(x)
|
||||
do_na <- plot_NA && any(is.na(x))
|
||||
if (do_na) {
|
||||
x_range <- diff(x_lim)
|
||||
loc_na <- min(x, na.rm = TRUE) + x_range * pos_NA
|
||||
@@ -272,8 +272,8 @@ xgb.shap.data <- function(data, shap_contrib = NULL, features = NULL, top_n = 1,
|
||||
imp <- xgb.importance(model = model, trees = trees, feature_names = colnames(data))
|
||||
}
|
||||
top_n <- top_n[1]
|
||||
if (top_n < 1 || top_n > 100) stop("top_n: must be an integer within [1, 100]")
|
||||
features <- imp$Feature[seq_len(min(top_n, NROW(imp)))]
|
||||
if (top_n < 1 | top_n > 100) stop("top_n: must be an integer within [1, 100]")
|
||||
features <- imp$Feature[1:min(top_n, NROW(imp))]
|
||||
}
|
||||
if (is.character(features)) {
|
||||
features <- match(features, colnames(data))
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#' The branches that also used for missing values are marked as bold
|
||||
#' (as in "carrying extra capacity").
|
||||
#'
|
||||
#' This function uses \href{https://www.graphviz.org/}{GraphViz} as a backend of DiagrammeR.
|
||||
#' This function uses \href{http://www.graphviz.org/}{GraphViz} as a backend of DiagrammeR.
|
||||
#'
|
||||
#' @return
|
||||
#'
|
||||
@@ -68,7 +68,7 @@
|
||||
#'
|
||||
#' @export
|
||||
xgb.plot.tree <- function(feature_names = NULL, model = NULL, trees = NULL, plot_width = NULL, plot_height = NULL,
|
||||
render = TRUE, show_node_id = FALSE, ...) {
|
||||
render = TRUE, show_node_id = FALSE, ...){
|
||||
check.deprecation(...)
|
||||
if (!inherits(model, "xgb.Booster")) {
|
||||
stop("model: Has to be an object of class xgb.Booster")
|
||||
@@ -98,22 +98,18 @@ xgb.plot.tree <- function(feature_names = NULL, model = NULL, trees = NULL, plot
|
||||
data = dt$Feature,
|
||||
fontcolor = "black")
|
||||
|
||||
if (nrow(dt[Feature != "Leaf"]) != 0) {
|
||||
edges <- DiagrammeR::create_edge_df(
|
||||
from = match(rep(dt[Feature != "Leaf", c(ID)], 2), dt$ID),
|
||||
to = match(dt[Feature != "Leaf", c(Yes, No)], dt$ID),
|
||||
label = c(
|
||||
dt[Feature != "Leaf", paste("<", Split)],
|
||||
rep("", nrow(dt[Feature != "Leaf"]))
|
||||
),
|
||||
style = c(
|
||||
dt[Feature != "Leaf", ifelse(Missing == Yes, "bold", "solid")],
|
||||
dt[Feature != "Leaf", ifelse(Missing == No, "bold", "solid")]
|
||||
),
|
||||
rel = "leading_to")
|
||||
} else {
|
||||
edges <- NULL
|
||||
}
|
||||
edges <- DiagrammeR::create_edge_df(
|
||||
from = match(rep(dt[Feature != "Leaf", c(ID)], 2), dt$ID),
|
||||
to = match(dt[Feature != "Leaf", c(Yes, No)], dt$ID),
|
||||
label = c(
|
||||
dt[Feature != "Leaf", paste("<", Split)],
|
||||
rep("", nrow(dt[Feature != "Leaf"]))
|
||||
),
|
||||
style = c(
|
||||
dt[Feature != "Leaf", ifelse(Missing == Yes, "bold", "solid")],
|
||||
dt[Feature != "Leaf", ifelse(Missing == No, "bold", "solid")]
|
||||
),
|
||||
rel = "leading_to")
|
||||
|
||||
graph <- DiagrammeR::create_graph(
|
||||
nodes_df = nodes,
|
||||
|
||||
@@ -4,14 +4,6 @@
|
||||
#' Save xgboost model from xgboost or xgb.train
|
||||
#'
|
||||
#' @param model the model object.
|
||||
#' @param raw_format The format for encoding the booster. Available options are
|
||||
#' \itemize{
|
||||
#' \item \code{json}: Encode the booster into JSON text document.
|
||||
#' \item \code{ubj}: Encode the booster into Universal Binary JSON.
|
||||
#' \item \code{deprecated}: Encode the booster into old customized binary format.
|
||||
#' }
|
||||
#'
|
||||
#' Right now the default is \code{deprecated} but will be changed to \code{ubj} in upcoming release.
|
||||
#'
|
||||
#' @examples
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
@@ -25,8 +17,7 @@
|
||||
#' pred <- predict(bst, test$data)
|
||||
#'
|
||||
#' @export
|
||||
xgb.save.raw <- function(model, raw_format = "deprecated") {
|
||||
xgb.save.raw <- function(model) {
|
||||
handle <- xgb.get.handle(model)
|
||||
args <- list(format = raw_format)
|
||||
.Call(XGBoosterSaveModelToRaw_R, handle, jsonlite::toJSON(args, auto_unbox = TRUE))
|
||||
.Call(XGBoosterModelToRaw_R, handle)
|
||||
}
|
||||
|
||||
@@ -18,37 +18,17 @@
|
||||
#' 2.1. Parameters for Tree Booster
|
||||
#'
|
||||
#' \itemize{
|
||||
#' \item{ \code{eta} control the learning rate: scale the contribution of each tree by a factor of \code{0 < eta < 1}
|
||||
#' when it is added to the current approximation.
|
||||
#' Used to prevent overfitting by making the boosting process more conservative.
|
||||
#' Lower value for \code{eta} implies larger value for \code{nrounds}: low \code{eta} value means model
|
||||
#' more robust to overfitting but slower to compute. Default: 0.3}
|
||||
#' \item{ \code{gamma} minimum loss reduction required to make a further partition on a leaf node of the tree.
|
||||
#' the larger, the more conservative the algorithm will be.}
|
||||
#' \item \code{eta} control the learning rate: scale the contribution of each tree by a factor of \code{0 < eta < 1} when it is added to the current approximation. Used to prevent overfitting by making the boosting process more conservative. Lower value for \code{eta} implies larger value for \code{nrounds}: low \code{eta} value means model more robust to overfitting but slower to compute. Default: 0.3
|
||||
#' \item \code{gamma} minimum loss reduction required to make a further partition on a leaf node of the tree. the larger, the more conservative the algorithm will be.
|
||||
#' \item \code{max_depth} maximum depth of a tree. Default: 6
|
||||
#' \item{\code{min_child_weight} minimum sum of instance weight (hessian) needed in a child.
|
||||
#' If the tree partition step results in a leaf node with the sum of instance weight less than min_child_weight,
|
||||
#' then the building process will give up further partitioning.
|
||||
#' In linear regression mode, this simply corresponds to minimum number of instances needed to be in each node.
|
||||
#' The larger, the more conservative the algorithm will be. Default: 1}
|
||||
#' \item{ \code{subsample} subsample ratio of the training instance.
|
||||
#' Setting it to 0.5 means that xgboost randomly collected half of the data instances to grow trees
|
||||
#' and this will prevent overfitting. It makes computation shorter (because less data to analyse).
|
||||
#' It is advised to use this parameter with \code{eta} and increase \code{nrounds}. Default: 1}
|
||||
#' \item \code{min_child_weight} minimum sum of instance weight (hessian) needed in a child. If the tree partition step results in a leaf node with the sum of instance weight less than min_child_weight, then the building process will give up further partitioning. In linear regression mode, this simply corresponds to minimum number of instances needed to be in each node. The larger, the more conservative the algorithm will be. Default: 1
|
||||
#' \item \code{subsample} subsample ratio of the training instance. Setting it to 0.5 means that xgboost randomly collected half of the data instances to grow trees and this will prevent overfitting. It makes computation shorter (because less data to analyse). It is advised to use this parameter with \code{eta} and increase \code{nrounds}. Default: 1
|
||||
#' \item \code{colsample_bytree} subsample ratio of columns when constructing each tree. Default: 1
|
||||
#' \item \code{lambda} L2 regularization term on weights. Default: 1
|
||||
#' \item \code{alpha} L1 regularization term on weights. (there is no L1 reg on bias because it is not important). Default: 0
|
||||
#' \item{ \code{num_parallel_tree} Experimental parameter. number of trees to grow per round.
|
||||
#' Useful to test Random Forest through XGBoost
|
||||
#' (set \code{colsample_bytree < 1}, \code{subsample < 1} and \code{round = 1}) accordingly.
|
||||
#' Default: 1}
|
||||
#' \item{ \code{monotone_constraints} A numerical vector consists of \code{1}, \code{0} and \code{-1} with its length
|
||||
#' equals to the number of features in the training data.
|
||||
#' \code{1} is increasing, \code{-1} is decreasing and \code{0} is no constraint.}
|
||||
#' \item{ \code{interaction_constraints} A list of vectors specifying feature indices of permitted interactions.
|
||||
#' Each item of the list represents one permitted interaction where specified features are allowed to interact with each other.
|
||||
#' Feature index values should start from \code{0} (\code{0} references the first column).
|
||||
#' Leave argument unspecified for no interaction constraints.}
|
||||
#' \item \code{num_parallel_tree} Experimental parameter. number of trees to grow per round. Useful to test Random Forest through XGBoost (set \code{colsample_bytree < 1}, \code{subsample < 1} and \code{round = 1}) accordingly. Default: 1
|
||||
#' \item \code{monotone_constraints} A numerical vector consists of \code{1}, \code{0} and \code{-1} with its length equals to the number of features in the training data. \code{1} is increasing, \code{-1} is decreasing and \code{0} is no constraint.
|
||||
#' \item \code{interaction_constraints} A list of vectors specifying feature indices of permitted interactions. Each item of the list represents one permitted interaction where specified features are allowed to interact with each other. Feature index values should start from \code{0} (\code{0} references the first column). Leave argument unspecified for no interaction constraints.
|
||||
#' }
|
||||
#'
|
||||
#' 2.2. Parameters for Linear Booster
|
||||
@@ -62,53 +42,29 @@
|
||||
#' 3. Task Parameters
|
||||
#'
|
||||
#' \itemize{
|
||||
#' \item{ \code{objective} specify the learning task and the corresponding learning objective, users can pass a self-defined function to it.
|
||||
#' The default objective options are below:
|
||||
#' \item \code{objective} specify the learning task and the corresponding learning objective, users can pass a self-defined function to it. The default objective options are below:
|
||||
#' \itemize{
|
||||
#' \item \code{reg:squarederror} Regression with squared loss (Default).
|
||||
#' \item{ \code{reg:squaredlogerror}: regression with squared log loss \eqn{1/2 * (log(pred + 1) - log(label + 1))^2}.
|
||||
#' All inputs are required to be greater than -1.
|
||||
#' Also, see metric rmsle for possible issue with this objective.}
|
||||
#' \item \code{reg:squaredlogerror}: regression with squared log loss \eqn{1/2 * (log(pred + 1) - log(label + 1))^2}. All inputs are required to be greater than -1. Also, see metric rmsle for possible issue with this objective.
|
||||
#' \item \code{reg:logistic} logistic regression.
|
||||
#' \item \code{reg:pseudohubererror}: regression with Pseudo Huber loss, a twice differentiable alternative to absolute loss.
|
||||
#' \item \code{binary:logistic} logistic regression for binary classification. Output probability.
|
||||
#' \item \code{binary:logitraw} logistic regression for binary classification, output score before logistic transformation.
|
||||
#' \item \code{binary:hinge}: hinge loss for binary classification. This makes predictions of 0 or 1, rather than producing probabilities.
|
||||
#' \item{ \code{count:poisson}: Poisson regression for count data, output mean of Poisson distribution.
|
||||
#' \code{max_delta_step} is set to 0.7 by default in poisson regression (used to safeguard optimization).}
|
||||
#' \item{ \code{survival:cox}: Cox regression for right censored survival time data (negative values are considered right censored).
|
||||
#' Note that predictions are returned on the hazard ratio scale (i.e., as HR = exp(marginal_prediction) in the proportional
|
||||
#' hazard function \code{h(t) = h0(t) * HR)}.}
|
||||
#' \item{ \code{survival:aft}: Accelerated failure time model for censored survival time data. See
|
||||
#' \href{https://xgboost.readthedocs.io/en/latest/tutorials/aft_survival_analysis.html}{Survival Analysis with Accelerated Failure Time}
|
||||
#' for details.}
|
||||
#' \item \code{count:poisson}: Poisson regression for count data, output mean of Poisson distribution. \code{max_delta_step} is set to 0.7 by default in poisson regression (used to safeguard optimization).
|
||||
#' \item \code{survival:cox}: Cox regression for right censored survival time data (negative values are considered right censored). Note that predictions are returned on the hazard ratio scale (i.e., as HR = exp(marginal_prediction) in the proportional hazard function \code{h(t) = h0(t) * HR)}.
|
||||
#' \item \code{survival:aft}: Accelerated failure time model for censored survival time data. See \href{https://xgboost.readthedocs.io/en/latest/tutorials/aft_survival_analysis.html}{Survival Analysis with Accelerated Failure Time} for details.
|
||||
#' \item \code{aft_loss_distribution}: Probability Density Function used by \code{survival:aft} and \code{aft-nloglik} metric.
|
||||
#' \item{ \code{multi:softmax} set xgboost to do multiclass classification using the softmax objective.
|
||||
#' Class is represented by a number and should be from 0 to \code{num_class - 1}.}
|
||||
#' \item{ \code{multi:softprob} same as softmax, but prediction outputs a vector of ndata * nclass elements, which can be
|
||||
#' further reshaped to ndata, nclass matrix. The result contains predicted probabilities of each data point belonging
|
||||
#' to each class.}
|
||||
#' \item \code{multi:softmax} set xgboost to do multiclass classification using the softmax objective. Class is represented by a number and should be from 0 to \code{num_class - 1}.
|
||||
#' \item \code{multi:softprob} same as softmax, but prediction outputs a vector of ndata * nclass elements, which can be further reshaped to ndata, nclass matrix. The result contains predicted probabilities of each data point belonging to each class.
|
||||
#' \item \code{rank:pairwise} set xgboost to do ranking task by minimizing the pairwise loss.
|
||||
#' \item{ \code{rank:ndcg}: Use LambdaMART to perform list-wise ranking where
|
||||
#' \href{https://en.wikipedia.org/wiki/Discounted_cumulative_gain}{Normalized Discounted Cumulative Gain (NDCG)} is maximized.}
|
||||
#' \item{ \code{rank:map}: Use LambdaMART to perform list-wise ranking where
|
||||
#' \href{https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)#Mean_average_precision}{Mean Average Precision (MAP)}
|
||||
#' is maximized.}
|
||||
#' \item{ \code{reg:gamma}: gamma regression with log-link.
|
||||
#' Output is a mean of gamma distribution.
|
||||
#' It might be useful, e.g., for modeling insurance claims severity, or for any outcome that might be
|
||||
#' \href{https://en.wikipedia.org/wiki/Gamma_distribution#Applications}{gamma-distributed}.}
|
||||
#' \item{ \code{reg:tweedie}: Tweedie regression with log-link.
|
||||
#' It might be useful, e.g., for modeling total loss in insurance, or for any outcome that might be
|
||||
#' \href{https://en.wikipedia.org/wiki/Tweedie_distribution#Applications}{Tweedie-distributed}.}
|
||||
#' \item \code{rank:ndcg}: Use LambdaMART to perform list-wise ranking where \href{https://en.wikipedia.org/wiki/Discounted_cumulative_gain}{Normalized Discounted Cumulative Gain (NDCG)} is maximized.
|
||||
#' \item \code{rank:map}: Use LambdaMART to perform list-wise ranking where \href{https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)#Mean_average_precision}{Mean Average Precision (MAP)} is maximized.
|
||||
#' \item \code{reg:gamma}: gamma regression with log-link. Output is a mean of gamma distribution. It might be useful, e.g., for modeling insurance claims severity, or for any outcome that might be \href{https://en.wikipedia.org/wiki/Gamma_distribution#Applications}{gamma-distributed}.
|
||||
#' \item \code{reg:tweedie}: Tweedie regression with log-link. It might be useful, e.g., for modeling total loss in insurance, or for any outcome that might be \href{https://en.wikipedia.org/wiki/Tweedie_distribution#Applications}{Tweedie-distributed}.
|
||||
#' }
|
||||
#' }
|
||||
#' \item \code{base_score} the initial prediction score of all instances, global bias. Default: 0.5
|
||||
#' \item{ \code{eval_metric} evaluation metrics for validation data.
|
||||
#' Users can pass a self-defined function to it.
|
||||
#' Default: metric will be assigned according to objective
|
||||
#' (rmse for regression, and error for classification, mean average precision for ranking).
|
||||
#' List is provided in detail section.}
|
||||
#' \item \code{eval_metric} evaluation metrics for validation data. Users can pass a self-defined function to it. Default: metric will be assigned according to objective(rmse for regression, and error for classification, mean average precision for ranking). List is provided in detail section.
|
||||
#' }
|
||||
#'
|
||||
#' @param data training dataset. \code{xgb.train} accepts only an \code{xgb.DMatrix} as the input.
|
||||
@@ -185,8 +141,7 @@
|
||||
#' \item \code{merror} Multiclass classification error rate. It is calculated as \code{(# wrong cases) / (# all cases)}.
|
||||
#' \item \code{mae} Mean absolute error
|
||||
#' \item \code{mape} Mean absolute percentage error
|
||||
#' \item{ \code{auc} Area under the curve.
|
||||
#' \url{https://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.}
|
||||
#' \item \code{auc} Area under the curve. \url{https://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.
|
||||
#' \item \code{aucpr} Area under the PR curve. \url{https://en.wikipedia.org/wiki/Precision_and_recall} for ranking evaluation.
|
||||
#' \item \code{ndcg} Normalized Discounted Cumulative Gain (for ranking task). \url{https://en.wikipedia.org/wiki/NDCG}
|
||||
#' }
|
||||
@@ -237,8 +192,8 @@
|
||||
#' data(agaricus.train, package='xgboost')
|
||||
#' data(agaricus.test, package='xgboost')
|
||||
#'
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtest <- with(agaricus.test, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
#' dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
#' dtest <- with(agaricus.test, xgb.DMatrix(data, label = label))
|
||||
#' watchlist <- list(train = dtrain, eval = dtest)
|
||||
#'
|
||||
#' ## A simple xgb.train example:
|
||||
@@ -321,10 +276,6 @@ xgb.train <- function(params = list(), data, nrounds, watchlist = list(),
|
||||
if (is.null(evnames) || any(evnames == ""))
|
||||
stop("each element of the watchlist must have a name tag")
|
||||
}
|
||||
# Handle multiple evaluation metrics given as a list
|
||||
for (m in params$eval_metric) {
|
||||
params <- c(params, list(eval_metric = m))
|
||||
}
|
||||
|
||||
# evaluation printing callback
|
||||
params <- c(params)
|
||||
@@ -393,7 +344,7 @@ xgb.train <- function(params = list(), data, nrounds, watchlist = list(),
|
||||
xgb.iter.update(bst$handle, dtrain, iteration - 1, obj)
|
||||
|
||||
if (length(watchlist) > 0)
|
||||
bst_evaluation <- xgb.iter.eval(bst$handle, watchlist, iteration - 1, feval) # nolint: object_usage_linter
|
||||
bst_evaluation <- xgb.iter.eval(bst$handle, watchlist, iteration - 1, feval)
|
||||
|
||||
xgb.attr(bst$handle, 'niter') <- iteration - 1
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ xgboost <- function(data = NULL, label = NULL, missing = NA, weight = NULL,
|
||||
early_stopping_rounds = NULL, maximize = NULL,
|
||||
save_period = NULL, save_name = "xgboost.model",
|
||||
xgb_model = NULL, callbacks = list(), ...) {
|
||||
merged <- check.booster.params(params, ...)
|
||||
dtrain <- xgb.get.DMatrix(data, label, missing, weight, nthread = merged$nthread)
|
||||
|
||||
dtrain <- xgb.get.DMatrix(data, label, missing, weight, nthread = params$nthread)
|
||||
|
||||
watchlist <- list(train = dtrain)
|
||||
|
||||
|
||||
1871
R-package/configure
vendored
1871
R-package/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -2,25 +2,10 @@
|
||||
|
||||
AC_PREREQ(2.69)
|
||||
|
||||
AC_INIT([xgboost],[2.0.0],[],[xgboost],[])
|
||||
AC_INIT([xgboost],[0.6-3],[],[xgboost],[])
|
||||
|
||||
: ${R_HOME=`R RHOME`}
|
||||
if test -z "${R_HOME}"; then
|
||||
echo "could not determine R_HOME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CXX17=`"${R_HOME}/bin/R" CMD config CXX17`
|
||||
CXX17STD=`"${R_HOME}/bin/R" CMD config CXX17STD`
|
||||
CXX="${CXX17} ${CXX17STD}"
|
||||
CXXFLAGS=`"${R_HOME}/bin/R" CMD config CXXFLAGS`
|
||||
|
||||
CC=`"${R_HOME}/bin/R" CMD config CC`
|
||||
CFLAGS=`"${R_HOME}/bin/R" CMD config CFLAGS`
|
||||
CPPFLAGS=`"${R_HOME}/bin/R" CMD config CPPFLAGS`
|
||||
|
||||
LDFLAGS=`"${R_HOME}/bin/R" CMD config LDFLAGS`
|
||||
AC_LANG(C++)
|
||||
# Use this line to set CC variable to a C compiler
|
||||
AC_PROG_CC
|
||||
|
||||
### Check whether backtrace() is part of libc or the external lib libexecinfo
|
||||
AC_MSG_CHECKING([Backtrace lib])
|
||||
@@ -43,19 +28,12 @@ fi
|
||||
|
||||
if test `uname -s` = "Darwin"
|
||||
then
|
||||
if command -v brew &> /dev/null
|
||||
then
|
||||
HOMEBREW_LIBOMP_PREFIX=`brew --prefix libomp`
|
||||
else
|
||||
# Homebrew not found
|
||||
HOMEBREW_LIBOMP_PREFIX=''
|
||||
fi
|
||||
OPENMP_CXXFLAGS="-Xpreprocessor -fopenmp -I${HOMEBREW_LIBOMP_PREFIX}/include"
|
||||
OPENMP_LIB="-lomp -L${HOMEBREW_LIBOMP_PREFIX}/lib"
|
||||
OPENMP_CXXFLAGS='-Xclang -fopenmp'
|
||||
OPENMP_LIB='-lomp'
|
||||
ac_pkg_openmp=no
|
||||
AC_MSG_CHECKING([whether OpenMP will work in a package])
|
||||
AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include <omp.h>]], [[ return (omp_get_max_threads() <= 1); ]])])
|
||||
${CXX} -o conftest conftest.cpp ${CPPFLAGS} ${LDFLAGS} ${OPENMP_LIB} ${OPENMP_CXXFLAGS} 2>/dev/null && ./conftest && ac_pkg_openmp=yes
|
||||
${CC} -o conftest conftest.c ${OPENMP_LIB} ${OPENMP_CXXFLAGS} 2>/dev/null && ./conftest && ac_pkg_openmp=yes
|
||||
AC_MSG_RESULT([${ac_pkg_openmp}])
|
||||
if test "${ac_pkg_openmp}" = no; then
|
||||
OPENMP_CXXFLAGS=''
|
||||
|
||||
@@ -63,7 +63,7 @@ print(paste("sum(abs(pred2-pred))=", sum(abs(pred2 - pred))))
|
||||
# save model to R's raw vector
|
||||
raw <- xgb.save.raw(bst)
|
||||
# load binary model to R
|
||||
bst3 <- xgb.load.raw(raw)
|
||||
bst3 <- xgb.load(raw)
|
||||
pred3 <- predict(bst3, test$data)
|
||||
# pred3 should be identical to pred
|
||||
print(paste("sum(abs(pred3-pred))=", sum(abs(pred3 - pred))))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# install development version of caret library that contains xgboost models
|
||||
devtools::install_github("topepo/caret/pkg/caret")
|
||||
require(caret)
|
||||
require(xgboost)
|
||||
require(data.table)
|
||||
@@ -7,23 +8,14 @@ require(e1071)
|
||||
|
||||
# Load Arthritis dataset in memory.
|
||||
data(Arthritis)
|
||||
# Create a copy of the dataset with data.table package
|
||||
# (data.table is 100% compliant with R dataframe but its syntax is a lot more consistent
|
||||
# and its performance are really good).
|
||||
# Create a copy of the dataset with data.table package (data.table is 100% compliant with R dataframe but its syntax is a lot more consistent and its performance are really good).
|
||||
df <- data.table(Arthritis, keep.rownames = FALSE)
|
||||
|
||||
# Let's add some new categorical features to see if it helps.
|
||||
# Of course these feature are highly correlated to the Age feature.
|
||||
# Usually it's not a good thing in ML, but Tree algorithms (including boosted trees) are able to select the best features,
|
||||
# even in case of highly correlated features.
|
||||
# For the first feature we create groups of age by rounding the real age.
|
||||
# Note that we transform it to factor (categorical data) so the algorithm treat them as independant values.
|
||||
# Let's add some new categorical features to see if it helps. Of course these feature are highly correlated to the Age feature. Usually it's not a good thing in ML, but Tree algorithms (including boosted trees) are able to select the best features, even in case of highly correlated features.
|
||||
# For the first feature we create groups of age by rounding the real age. Note that we transform it to factor (categorical data) so the algorithm treat them as independant values.
|
||||
df[, AgeDiscret := as.factor(round(Age / 10, 0))]
|
||||
|
||||
# Here is an even stronger simplification of the real age with an arbitrary split at 30 years old.
|
||||
# I choose this value based on nothing.
|
||||
# We will see later if simplifying the information based on arbitrary values is a good strategy
|
||||
# (I am sure you already have an idea of how well it will work!).
|
||||
# Here is an even stronger simplification of the real age with an arbitrary split at 30 years old. I choose this value based on nothing. We will see later if simplifying the information based on arbitrary values is a good strategy (I am sure you already have an idea of how well it will work!).
|
||||
df[, AgeCat := as.factor(ifelse(Age > 30, "Old", "Young"))]
|
||||
|
||||
# We remove ID as there is nothing to learn from this feature (it will just add some noise as the dataset is small).
|
||||
@@ -34,10 +26,9 @@ df[, ID := NULL]
|
||||
# Here we use 10-fold cross-validation, repeating twice, and using random search for tuning hyper-parameters.
|
||||
fitControl <- trainControl(method = "repeatedcv", number = 10, repeats = 2, search = "random")
|
||||
# train a xgbTree model using caret::train
|
||||
model <- train(factor(Improved) ~ ., data = df, method = "xgbTree", trControl = fitControl)
|
||||
model <- train(factor(Improved)~., data = df, method = "xgbTree", trControl = fitControl)
|
||||
|
||||
# Instead of tree for our boosters, you can also fit a linear regression or logistic regression model
|
||||
# using xgbLinear
|
||||
# Instead of tree for our boosters, you can also fit a linear regression or logistic regression model using xgbLinear
|
||||
# model <- train(factor(Improved)~., data = df, method = "xgbLinear", trControl = fitControl)
|
||||
|
||||
# See model results
|
||||
|
||||
@@ -7,47 +7,34 @@ if (!require(vcd)) {
|
||||
}
|
||||
# According to its documentation, XGBoost works only on numbers.
|
||||
# Sometimes the dataset we have to work on have categorical data.
|
||||
# A categorical variable is one which have a fixed number of values.
|
||||
# By example, if for each observation a variable called "Colour" can have only
|
||||
# "red", "blue" or "green" as value, it is a categorical variable.
|
||||
# A categorical variable is one which have a fixed number of values. By example, if for each observation a variable called "Colour" can have only "red", "blue" or "green" as value, it is a categorical variable.
|
||||
#
|
||||
# In R, categorical variable is called Factor.
|
||||
# Type ?factor in console for more information.
|
||||
#
|
||||
# In this demo we will see how to transform a dense dataframe with categorical variables to a sparse matrix
|
||||
# before analyzing it in XGBoost.
|
||||
# In this demo we will see how to transform a dense dataframe with categorical variables to a sparse matrix before analyzing it in XGBoost.
|
||||
# The method we are going to see is usually called "one hot encoding".
|
||||
|
||||
#load Arthritis dataset in memory.
|
||||
data(Arthritis)
|
||||
|
||||
# create a copy of the dataset with data.table package
|
||||
# (data.table is 100% compliant with R dataframe but its syntax is a lot more consistent
|
||||
# and its performance are really good).
|
||||
# create a copy of the dataset with data.table package (data.table is 100% compliant with R dataframe but its syntax is a lot more consistent and its performance are really good).
|
||||
df <- data.table(Arthritis, keep.rownames = FALSE)
|
||||
|
||||
# Let's have a look to the data.table
|
||||
cat("Print the dataset\n")
|
||||
print(df)
|
||||
|
||||
# 2 columns have factor type, one has ordinal type
|
||||
# (ordinal variable is a categorical variable with values which can be ordered, here: None > Some > Marked).
|
||||
# 2 columns have factor type, one has ordinal type (ordinal variable is a categorical variable with values which can be ordered, here: None > Some > Marked).
|
||||
cat("Structure of the dataset\n")
|
||||
str(df)
|
||||
|
||||
# Let's add some new categorical features to see if it helps.
|
||||
# Of course these feature are highly correlated to the Age feature.
|
||||
# Usually it's not a good thing in ML, but Tree algorithms (including boosted trees) are able to select the best features,
|
||||
# even in case of highly correlated features.
|
||||
# Let's add some new categorical features to see if it helps. Of course these feature are highly correlated to the Age feature. Usually it's not a good thing in ML, but Tree algorithms (including boosted trees) are able to select the best features, even in case of highly correlated features.
|
||||
|
||||
# For the first feature we create groups of age by rounding the real age.
|
||||
# Note that we transform it to factor (categorical data) so the algorithm treat them as independent values.
|
||||
# For the first feature we create groups of age by rounding the real age. Note that we transform it to factor (categorical data) so the algorithm treat them as independent values.
|
||||
df[, AgeDiscret := as.factor(round(Age / 10, 0))]
|
||||
|
||||
# Here is an even stronger simplification of the real age with an arbitrary split at 30 years old.
|
||||
# I choose this value based on nothing.
|
||||
# We will see later if simplifying the information based on arbitrary values is a good strategy
|
||||
# (I am sure you already have an idea of how well it will work!).
|
||||
# Here is an even stronger simplification of the real age with an arbitrary split at 30 years old. I choose this value based on nothing. We will see later if simplifying the information based on arbitrary values is a good strategy (I am sure you already have an idea of how well it will work!).
|
||||
df[, AgeCat := as.factor(ifelse(Age > 30, "Old", "Young"))]
|
||||
|
||||
# We remove ID as there is nothing to learn from this feature (it will just add some noise as the dataset is small).
|
||||
@@ -61,10 +48,7 @@ print(levels(df[, Treatment]))
|
||||
# This method is also called one hot encoding.
|
||||
# The purpose is to transform each value of each categorical feature in one binary feature.
|
||||
#
|
||||
# Let's take, the column Treatment will be replaced by two columns, Placebo, and Treated.
|
||||
# Each of them will be binary.
|
||||
# For example an observation which had the value Placebo in column Treatment before the transformation will have, after the transformation,
|
||||
# the value 1 in the new column Placebo and the value 0 in the new column Treated.
|
||||
# Let's take, the column Treatment will be replaced by two columns, Placebo, and Treated. Each of them will be binary. For example an observation which had the value Placebo in column Treatment before the transformation will have, after the transformation, the value 1 in the new column Placebo and the value 0 in the new column Treated.
|
||||
#
|
||||
# Formulae Improved~.-1 used below means transform all categorical features but column Improved to binary values.
|
||||
# Column Improved is excluded because it will be our output column, the one we want to predict.
|
||||
@@ -86,10 +70,7 @@ bst <- xgboost(data = sparse_matrix, label = output_vector, max_depth = 9,
|
||||
|
||||
importance <- xgb.importance(feature_names = colnames(sparse_matrix), model = bst)
|
||||
print(importance)
|
||||
# According to the matrix below, the most important feature in this dataset to predict if the treatment will work is the Age.
|
||||
# The second most important feature is having received a placebo or not.
|
||||
# The sex is third.
|
||||
# Then we see our generated features (AgeDiscret). We can see that their contribution is very low (Gain column).
|
||||
# According to the matrix below, the most important feature in this dataset to predict if the treatment will work is the Age. The second most important feature is having received a placebo or not. The sex is third. Then we see our generated features (AgeDiscret). We can see that their contribution is very low (Gain column).
|
||||
|
||||
# Does these result make sense?
|
||||
# Let's check some Chi2 between each of these features and the outcome.
|
||||
@@ -101,17 +82,8 @@ print(chisq.test(df$AgeDiscret, df$Y))
|
||||
# Our first simplification of Age gives a Pearson correlation of 8.
|
||||
|
||||
print(chisq.test(df$AgeCat, df$Y))
|
||||
# The perfectly random split I did between young and old at 30 years old have a low correlation of 2.
|
||||
# It's a result we may expect as may be in my mind > 30 years is being old (I am 32 and starting feeling old, this may explain that),
|
||||
# but for the illness we are studying, the age to be vulnerable is not the same.
|
||||
# Don't let your "gut" lower the quality of your model. In "data science", there is science :-)
|
||||
# The perfectly random split I did between young and old at 30 years old have a low correlation of 2. It's a result we may expect as may be in my mind > 30 years is being old (I am 32 and starting feeling old, this may explain that), but for the illness we are studying, the age to be vulnerable is not the same. Don't let your "gut" lower the quality of your model. In "data science", there is science :-)
|
||||
|
||||
# As you can see, in general destroying information by simplifying it won't improve your model.
|
||||
# Chi2 just demonstrates that.
|
||||
# But in more complex cases, creating a new feature based on existing one which makes link with the outcome
|
||||
# more obvious may help the algorithm and improve the model.
|
||||
# The case studied here is not enough complex to show that. Check Kaggle forum for some challenging datasets.
|
||||
# As you can see, in general destroying information by simplifying it won't improve your model. Chi2 just demonstrates that. But in more complex cases, creating a new feature based on existing one which makes link with the outcome more obvious may help the algorithm and improve the model. The case studied here is not enough complex to show that. Check Kaggle forum for some challenging datasets.
|
||||
# However it's almost always worse when you add some arbitrary rules.
|
||||
# Moreover, you can notice that even if we have added some not useful new features highly correlated with
|
||||
# other features, the boosting tree algorithm have been able to choose the best one, which in this case is the Age.
|
||||
# Linear model may not be that strong in these scenario.
|
||||
# Moreover, you can notice that even if we have added some not useful new features highly correlated with other features, the boosting tree algorithm have been able to choose the best one, which in this case is the Age. Linear model may not be that strong in these scenario.
|
||||
|
||||
@@ -12,7 +12,7 @@ cat('running cross validation\n')
|
||||
# do cross validation, this will print result out as
|
||||
# [iteration] metric_name:mean_value+std_value
|
||||
# std_value is standard deviation of the metric
|
||||
xgb.cv(param, dtrain, nrounds, nfold = 5, metrics = 'error')
|
||||
xgb.cv(param, dtrain, nrounds, nfold = 5, metrics = {'error'})
|
||||
|
||||
cat('running cross validation, disable standard deviation display\n')
|
||||
# do cross validation, this will print result out as
|
||||
|
||||
@@ -33,7 +33,7 @@ treeInteractions <- function(input_tree, input_max_depth) {
|
||||
}
|
||||
|
||||
# Extract nodes with interactions
|
||||
interaction_trees <- trees[!is.na(Split) & !is.na(parent_1), # nolint: object_usage_linter
|
||||
interaction_trees <- trees[!is.na(Split) & !is.na(parent_1),
|
||||
c('Feature', paste0('parent_feat_', 1:(input_max_depth - 1))),
|
||||
with = FALSE]
|
||||
interaction_trees_split <- split(interaction_trees, seq_len(nrow(interaction_trees)))
|
||||
|
||||
@@ -24,7 +24,7 @@ accuracy.before <- (sum((predict(bst, agaricus.test$data) >= 0.5) == agaricus.te
|
||||
pred_with_leaf <- predict(bst, dtest, predleaf = TRUE)
|
||||
head(pred_with_leaf)
|
||||
|
||||
create.new.tree.features <- function(model, original.features) {
|
||||
create.new.tree.features <- function(model, original.features){
|
||||
pred_with_leaf <- predict(model, original.features, predleaf = TRUE)
|
||||
cols <- list()
|
||||
for (i in 1:model$niter) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# running all scripts in demo folder, removed during packaging.
|
||||
# running all scripts in demo folder
|
||||
demo(basic_walkthrough, package = 'xgboost')
|
||||
demo(custom_objective, package = 'xgboost')
|
||||
demo(boost_from_prediction, package = 'xgboost')
|
||||
|
||||
@@ -79,9 +79,9 @@ end_of_table <- empty_lines[empty_lines > start_index][1L]
|
||||
|
||||
# Read the contents of the table
|
||||
exported_symbols <- objdump_results[(start_index + 1L):end_of_table]
|
||||
exported_symbols <- gsub("\t", "", exported_symbols, fixed = TRUE)
|
||||
exported_symbols <- gsub("\t", "", exported_symbols)
|
||||
exported_symbols <- gsub(".*\\] ", "", exported_symbols)
|
||||
exported_symbols <- gsub(" ", "", exported_symbols, fixed = TRUE)
|
||||
exported_symbols <- gsub(" ", "", exported_symbols)
|
||||
|
||||
# Write R.def file
|
||||
writeLines(
|
||||
|
||||
@@ -15,11 +15,9 @@ selected per iteration.}
|
||||
}
|
||||
\value{
|
||||
Results are stored in the \code{coefs} element of the closure.
|
||||
The \code{\link{xgb.gblinear.history}} convenience function provides an easy
|
||||
way to access it.
|
||||
The \code{\link{xgb.gblinear.history}} convenience function provides an easy way to access it.
|
||||
With \code{xgb.train}, it is either a dense of a sparse matrix.
|
||||
While with \code{xgb.cv}, it is a list (an element per each fold) of such
|
||||
matrices.
|
||||
While with \code{xgb.cv}, it is a list (an element per each fold) of such matrices.
|
||||
}
|
||||
\description{
|
||||
Callback closure for collecting the model coefficients history of a gblinear booster
|
||||
@@ -40,7 +38,7 @@ Callback function expects the following values to be set in its calling frame:
|
||||
# without considering the 2nd order interactions:
|
||||
x <- model.matrix(Species ~ .^2, iris)[,-1]
|
||||
colnames(x)
|
||||
dtrain <- xgb.DMatrix(scale(x), label = 1*(iris$Species == "versicolor"), nthread = 2)
|
||||
dtrain <- xgb.DMatrix(scale(x), label = 1*(iris$Species == "versicolor"))
|
||||
param <- list(booster = "gblinear", objective = "reg:logistic", eval_metric = "auc",
|
||||
lambda = 0.0003, alpha = 0.0003, nthread = 2)
|
||||
# For 'shotgun', which is a default linear updater, using high eta values may result in
|
||||
@@ -65,19 +63,19 @@ matplot(xgb.gblinear.history(bst), type = 'l')
|
||||
|
||||
# For xgb.cv:
|
||||
bst <- xgb.cv(param, dtrain, nfold = 5, nrounds = 100, eta = 0.8,
|
||||
callbacks = list(cb.gblinear.history()))
|
||||
callbacks = list(cb.gblinear.history()))
|
||||
# coefficients in the CV fold #3
|
||||
matplot(xgb.gblinear.history(bst)[[3]], type = 'l')
|
||||
|
||||
|
||||
#### Multiclass classification:
|
||||
#
|
||||
dtrain <- xgb.DMatrix(scale(x), label = as.numeric(iris$Species) - 1, nthread = 1)
|
||||
dtrain <- xgb.DMatrix(scale(x), label = as.numeric(iris$Species) - 1)
|
||||
param <- list(booster = "gblinear", objective = "multi:softprob", num_class = 3,
|
||||
lambda = 0.0003, alpha = 0.0003, nthread = 1)
|
||||
lambda = 0.0003, alpha = 0.0003, nthread = 2)
|
||||
# For the default linear updater 'shotgun' it sometimes is helpful
|
||||
# to use smaller eta to reduce instability
|
||||
bst <- xgb.train(param, dtrain, list(tr=dtrain), nrounds = 50, eta = 0.5,
|
||||
bst <- xgb.train(param, dtrain, list(tr=dtrain), nrounds = 70, eta = 0.5,
|
||||
callbacks = list(cb.gblinear.history()))
|
||||
# Will plot the coefficient paths separately for each class:
|
||||
matplot(xgb.gblinear.history(bst, class_index = 0), type = 'l')
|
||||
|
||||
@@ -19,7 +19,7 @@ be directly used with an \code{xgb.DMatrix} object.
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
train <- agaricus.train
|
||||
dtrain <- xgb.DMatrix(train$data, label=train$label, nthread = 2)
|
||||
dtrain <- xgb.DMatrix(train$data, label=train$label)
|
||||
|
||||
stopifnot(nrow(dtrain) == nrow(train$data))
|
||||
stopifnot(ncol(dtrain) == ncol(train$data))
|
||||
|
||||
@@ -26,7 +26,7 @@ Since row names are irrelevant, it is recommended to use \code{colnames} directl
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
train <- agaricus.train
|
||||
dtrain <- xgb.DMatrix(train$data, label=train$label, nthread = 2)
|
||||
dtrain <- xgb.DMatrix(train$data, label=train$label)
|
||||
dimnames(dtrain)
|
||||
colnames(dtrain)
|
||||
colnames(dtrain) <- make.names(1:ncol(train$data))
|
||||
|
||||
@@ -34,7 +34,7 @@ The \code{name} field can be one of the following:
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
|
||||
labels <- getinfo(dtrain, 'label')
|
||||
setinfo(dtrain, 'label', 1-labels)
|
||||
|
||||
@@ -27,11 +27,7 @@
|
||||
\arguments{
|
||||
\item{object}{Object of class \code{xgb.Booster} or \code{xgb.Booster.handle}}
|
||||
|
||||
\item{newdata}{takes \code{matrix}, \code{dgCMatrix}, \code{dgRMatrix}, \code{dsparseVector},
|
||||
local data file or \code{xgb.DMatrix}.
|
||||
|
||||
For single-row predictions on sparse data, it's recommended to use CSR format. If passing
|
||||
a sparse vector, it will take it as a row vector.}
|
||||
\item{newdata}{takes \code{matrix}, \code{dgCMatrix}, local data file or \code{xgb.DMatrix}.}
|
||||
|
||||
\item{missing}{Missing is only used when input is dense matrix. Pick a float value that represents
|
||||
missing values in data (e.g., sometimes 0 or some other extreme value is used).}
|
||||
@@ -59,7 +55,7 @@ training predicting will perform dropout.}
|
||||
|
||||
\item{iterationrange}{Specifies which layer of trees are used in prediction. For
|
||||
example, if a random forest is trained with 100 rounds. Specifying
|
||||
`iterationrange=(1, 21)`, then only the forests built during [1, 21) (half open set)
|
||||
`iteration_range=(1, 21)`, then only the forests built during [1, 21) (half open set)
|
||||
rounds are used in this prediction. It's 1-based index just like R vector. When set
|
||||
to \code{c(1, 1)} XGBoost will use all trees.}
|
||||
|
||||
@@ -122,10 +118,6 @@ With \code{predinteraction = TRUE}, SHAP values of contributions of interaction
|
||||
are computed. Note that this operation might be rather expensive in terms of compute and memory.
|
||||
Since it quadratically depends on the number of features, it is recommended to perform selection
|
||||
of the most important features first. See below about the format of the returned results.
|
||||
|
||||
The \code{predict()} method uses as many threads as defined in \code{xgb.Booster} object (all by default).
|
||||
If you want to change their number, then assign a new number to \code{nthread} using \code{\link{xgb.parameters<-}}.
|
||||
Note also that converting a matrix to \code{\link{xgb.DMatrix}} uses multiple threads too.
|
||||
}
|
||||
\examples{
|
||||
## binary classification:
|
||||
|
||||
@@ -19,7 +19,7 @@ Currently it displays dimensions and presence of info-fields and colnames.
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
|
||||
dtrain
|
||||
print(dtrain, verbose=TRUE)
|
||||
|
||||
@@ -33,7 +33,7 @@ The \code{name} field can be one of the following:
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
|
||||
labels <- getinfo(dtrain, 'label')
|
||||
setinfo(dtrain, 'label', 1-labels)
|
||||
|
||||
@@ -28,7 +28,7 @@ original xgb.DMatrix object
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
|
||||
dsub <- slice(dtrain, 1:42)
|
||||
labels1 <- getinfo(dsub, 'label')
|
||||
|
||||
@@ -4,20 +4,11 @@
|
||||
\alias{xgb.DMatrix}
|
||||
\title{Construct xgb.DMatrix object}
|
||||
\usage{
|
||||
xgb.DMatrix(
|
||||
data,
|
||||
info = list(),
|
||||
missing = NA,
|
||||
silent = FALSE,
|
||||
nthread = NULL,
|
||||
...
|
||||
)
|
||||
xgb.DMatrix(data, info = list(), missing = NA, silent = FALSE, ...)
|
||||
}
|
||||
\arguments{
|
||||
\item{data}{a \code{matrix} object (either numeric or integer), a \code{dgCMatrix} object,
|
||||
a \code{dgRMatrix} object (only when making predictions from a fitted model),
|
||||
a \code{dsparseVector} object (only when making predictions from a fitted model, will be
|
||||
interpreted as a row vector), or a character string representing a filename.}
|
||||
\item{data}{a \code{matrix} object (either numeric or integer), a \code{dgCMatrix} object, or a character
|
||||
string representing a filename.}
|
||||
|
||||
\item{info}{a named list of additional information to store in the \code{xgb.DMatrix} object.
|
||||
See \code{\link{setinfo}} for the specific allowed kinds of}
|
||||
@@ -27,8 +18,6 @@ It is useful when a 0 or some other extreme value represents missing values in d
|
||||
|
||||
\item{silent}{whether to suppress printing an informational message after loading from a file.}
|
||||
|
||||
\item{nthread}{Number of threads used for creating DMatrix.}
|
||||
|
||||
\item{...}{the \code{info} data could be passed directly as parameters, without creating an \code{info} list.}
|
||||
}
|
||||
\description{
|
||||
@@ -38,7 +27,7 @@ Supported input file formats are either a LIBSVM text file or a binary file that
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
xgb.DMatrix.save(dtrain, 'xgb.DMatrix.data')
|
||||
dtrain <- xgb.DMatrix('xgb.DMatrix.data')
|
||||
if (file.exists('xgb.DMatrix.data')) file.remove('xgb.DMatrix.data')
|
||||
|
||||
@@ -16,7 +16,7 @@ Save xgb.DMatrix object to binary file
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
xgb.DMatrix.save(dtrain, 'xgb.DMatrix.data')
|
||||
dtrain <- xgb.DMatrix('xgb.DMatrix.data')
|
||||
if (file.exists('xgb.DMatrix.data')) file.remove('xgb.DMatrix.data')
|
||||
|
||||
@@ -29,7 +29,7 @@ Joaquin Quinonero Candela)}
|
||||
|
||||
International Workshop on Data Mining for Online Advertising (ADKDD) - August 24, 2014
|
||||
|
||||
\url{https://research.facebook.com/publications/practical-lessons-from-predicting-clicks-on-ads-at-facebook/}.
|
||||
\url{https://research.fb.com/publications/practical-lessons-from-predicting-clicks-on-ads-at-facebook/}.
|
||||
|
||||
Extract explaining the method:
|
||||
|
||||
@@ -59,8 +59,8 @@ a rule on certain features."
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
data(agaricus.test, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtest <- with(agaricus.test, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
dtest <- with(agaricus.test, xgb.DMatrix(data, label = label))
|
||||
|
||||
param <- list(max_depth=2, eta=1, silent=1, objective='binary:logistic')
|
||||
nrounds = 4
|
||||
@@ -76,12 +76,8 @@ new.features.train <- xgb.create.features(model = bst, agaricus.train$data)
|
||||
new.features.test <- xgb.create.features(model = bst, agaricus.test$data)
|
||||
|
||||
# learning with new features
|
||||
new.dtrain <- xgb.DMatrix(
|
||||
data = new.features.train, label = agaricus.train$label, nthread = 2
|
||||
)
|
||||
new.dtest <- xgb.DMatrix(
|
||||
data = new.features.test, label = agaricus.test$label, nthread = 2
|
||||
)
|
||||
new.dtrain <- xgb.DMatrix(data = new.features.train, label = agaricus.train$label)
|
||||
new.dtest <- xgb.DMatrix(data = new.features.test, label = agaricus.test$label)
|
||||
watchlist <- list(train = new.dtrain)
|
||||
bst <- xgb.train(params = param, data = new.dtrain, nrounds = nrounds, nthread = 2)
|
||||
|
||||
|
||||
@@ -148,11 +148,9 @@ The cross validation function of xgboost
|
||||
\details{
|
||||
The original sample is randomly partitioned into \code{nfold} equal size subsamples.
|
||||
|
||||
Of the \code{nfold} subsamples, a single subsample is retained as the validation data for testing the model,
|
||||
and the remaining \code{nfold - 1} subsamples are used as training data.
|
||||
Of the \code{nfold} subsamples, a single subsample is retained as the validation data for testing the model, and the remaining \code{nfold - 1} subsamples are used as training data.
|
||||
|
||||
The cross-validation process is then repeated \code{nrounds} times, with each of the
|
||||
\code{nfold} subsamples used exactly once as the validation data.
|
||||
The cross-validation process is then repeated \code{nrounds} times, with each of the \code{nfold} subsamples used exactly once as the validation data.
|
||||
|
||||
All observations are used for both training and validation.
|
||||
|
||||
@@ -160,9 +158,9 @@ Adapted from \url{https://en.wikipedia.org/wiki/Cross-validation_\%28statistics\
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
cv <- xgb.cv(data = dtrain, nrounds = 3, nthread = 2, nfold = 5, metrics = list("rmse","auc"),
|
||||
max_depth = 3, eta = 1, objective = "binary:logistic")
|
||||
max_depth = 3, eta = 1, objective = "binary:logistic")
|
||||
print(cv)
|
||||
print(cv, verbose=TRUE)
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ xgb.dump(
|
||||
If not provided or set to \code{NULL}, the model is returned as a \code{character} vector.}
|
||||
|
||||
\item{fmap}{feature map file representing feature types.
|
||||
Detailed description could be found at
|
||||
\url{https://github.com/dmlc/xgboost/wiki/Binary-Classification#dump-model}.
|
||||
See demo/ for walkthrough example in R, and
|
||||
\url{https://github.com/dmlc/xgboost/blob/master/demo/data/featmap.txt}
|
||||
for example Format.}
|
||||
|
||||
@@ -16,7 +16,7 @@ An object of \code{xgb.Booster} class.
|
||||
Load xgboost model from the binary model file.
|
||||
}
|
||||
\details{
|
||||
The input file is expected to contain a model saved in an xgboost model format
|
||||
The input file is expected to contain a model saved in an xgboost-internal binary format
|
||||
using either \code{\link{xgb.save}} or \code{\link{cb.save.model}} in R, or using some
|
||||
appropriate methods from other xgboost interfaces. E.g., a model trained in Python and
|
||||
saved from there in xgboost format, could be loaded from R.
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
\alias{xgb.load.raw}
|
||||
\title{Load serialised xgboost model from R's raw vector}
|
||||
\usage{
|
||||
xgb.load.raw(buffer, as_booster = FALSE)
|
||||
xgb.load.raw(buffer)
|
||||
}
|
||||
\arguments{
|
||||
\item{buffer}{the buffer returned by xgb.save.raw}
|
||||
|
||||
\item{as_booster}{Return the loaded model as xgb.Booster instead of xgb.Booster.handle.}
|
||||
}
|
||||
\description{
|
||||
User can generate raw memory buffer by calling xgb.save.raw
|
||||
|
||||
@@ -10,7 +10,7 @@ xgb.ggplot.importance(
|
||||
top_n = NULL,
|
||||
measure = NULL,
|
||||
rel_to_first = FALSE,
|
||||
n_clusters = seq_len(10),
|
||||
n_clusters = c(1:10),
|
||||
...
|
||||
)
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ The "Yes" branches are marked by the "< split_value" label.
|
||||
The branches that also used for missing values are marked as bold
|
||||
(as in "carrying extra capacity").
|
||||
|
||||
This function uses \href{https://www.graphviz.org/}{GraphViz} as a backend of DiagrammeR.
|
||||
This function uses \href{http://www.graphviz.org/}{GraphViz} as a backend of DiagrammeR.
|
||||
}
|
||||
\examples{
|
||||
data(agaricus.train, package='xgboost')
|
||||
|
||||
@@ -5,19 +5,10 @@
|
||||
\title{Save xgboost model to R's raw vector,
|
||||
user can call xgb.load.raw to load the model back from raw vector}
|
||||
\usage{
|
||||
xgb.save.raw(model, raw_format = "deprecated")
|
||||
xgb.save.raw(model)
|
||||
}
|
||||
\arguments{
|
||||
\item{model}{the model object.}
|
||||
|
||||
\item{raw_format}{The format for encoding the booster. Available options are
|
||||
\itemize{
|
||||
\item \code{json}: Encode the booster into JSON text document.
|
||||
\item \code{ubj}: Encode the booster into Universal Binary JSON.
|
||||
\item \code{deprecated}: Encode the booster into old customized binary format.
|
||||
}
|
||||
|
||||
Right now the default is \code{deprecated} but will be changed to \code{ubj} in upcoming release.}
|
||||
}
|
||||
\description{
|
||||
Save xgboost model from xgboost or xgb.train
|
||||
|
||||
@@ -57,37 +57,17 @@ xgboost(
|
||||
2.1. Parameters for Tree Booster
|
||||
|
||||
\itemize{
|
||||
\item{ \code{eta} control the learning rate: scale the contribution of each tree by a factor of \code{0 < eta < 1}
|
||||
when it is added to the current approximation.
|
||||
Used to prevent overfitting by making the boosting process more conservative.
|
||||
Lower value for \code{eta} implies larger value for \code{nrounds}: low \code{eta} value means model
|
||||
more robust to overfitting but slower to compute. Default: 0.3}
|
||||
\item{ \code{gamma} minimum loss reduction required to make a further partition on a leaf node of the tree.
|
||||
the larger, the more conservative the algorithm will be.}
|
||||
\item \code{eta} control the learning rate: scale the contribution of each tree by a factor of \code{0 < eta < 1} when it is added to the current approximation. Used to prevent overfitting by making the boosting process more conservative. Lower value for \code{eta} implies larger value for \code{nrounds}: low \code{eta} value means model more robust to overfitting but slower to compute. Default: 0.3
|
||||
\item \code{gamma} minimum loss reduction required to make a further partition on a leaf node of the tree. the larger, the more conservative the algorithm will be.
|
||||
\item \code{max_depth} maximum depth of a tree. Default: 6
|
||||
\item{\code{min_child_weight} minimum sum of instance weight (hessian) needed in a child.
|
||||
If the tree partition step results in a leaf node with the sum of instance weight less than min_child_weight,
|
||||
then the building process will give up further partitioning.
|
||||
In linear regression mode, this simply corresponds to minimum number of instances needed to be in each node.
|
||||
The larger, the more conservative the algorithm will be. Default: 1}
|
||||
\item{ \code{subsample} subsample ratio of the training instance.
|
||||
Setting it to 0.5 means that xgboost randomly collected half of the data instances to grow trees
|
||||
and this will prevent overfitting. It makes computation shorter (because less data to analyse).
|
||||
It is advised to use this parameter with \code{eta} and increase \code{nrounds}. Default: 1}
|
||||
\item \code{min_child_weight} minimum sum of instance weight (hessian) needed in a child. If the tree partition step results in a leaf node with the sum of instance weight less than min_child_weight, then the building process will give up further partitioning. In linear regression mode, this simply corresponds to minimum number of instances needed to be in each node. The larger, the more conservative the algorithm will be. Default: 1
|
||||
\item \code{subsample} subsample ratio of the training instance. Setting it to 0.5 means that xgboost randomly collected half of the data instances to grow trees and this will prevent overfitting. It makes computation shorter (because less data to analyse). It is advised to use this parameter with \code{eta} and increase \code{nrounds}. Default: 1
|
||||
\item \code{colsample_bytree} subsample ratio of columns when constructing each tree. Default: 1
|
||||
\item \code{lambda} L2 regularization term on weights. Default: 1
|
||||
\item \code{alpha} L1 regularization term on weights. (there is no L1 reg on bias because it is not important). Default: 0
|
||||
\item{ \code{num_parallel_tree} Experimental parameter. number of trees to grow per round.
|
||||
Useful to test Random Forest through XGBoost
|
||||
(set \code{colsample_bytree < 1}, \code{subsample < 1} and \code{round = 1}) accordingly.
|
||||
Default: 1}
|
||||
\item{ \code{monotone_constraints} A numerical vector consists of \code{1}, \code{0} and \code{-1} with its length
|
||||
equals to the number of features in the training data.
|
||||
\code{1} is increasing, \code{-1} is decreasing and \code{0} is no constraint.}
|
||||
\item{ \code{interaction_constraints} A list of vectors specifying feature indices of permitted interactions.
|
||||
Each item of the list represents one permitted interaction where specified features are allowed to interact with each other.
|
||||
Feature index values should start from \code{0} (\code{0} references the first column).
|
||||
Leave argument unspecified for no interaction constraints.}
|
||||
\item \code{num_parallel_tree} Experimental parameter. number of trees to grow per round. Useful to test Random Forest through XGBoost (set \code{colsample_bytree < 1}, \code{subsample < 1} and \code{round = 1}) accordingly. Default: 1
|
||||
\item \code{monotone_constraints} A numerical vector consists of \code{1}, \code{0} and \code{-1} with its length equals to the number of features in the training data. \code{1} is increasing, \code{-1} is decreasing and \code{0} is no constraint.
|
||||
\item \code{interaction_constraints} A list of vectors specifying feature indices of permitted interactions. Each item of the list represents one permitted interaction where specified features are allowed to interact with each other. Feature index values should start from \code{0} (\code{0} references the first column). Leave argument unspecified for no interaction constraints.
|
||||
}
|
||||
|
||||
2.2. Parameters for Linear Booster
|
||||
@@ -101,53 +81,29 @@ xgboost(
|
||||
3. Task Parameters
|
||||
|
||||
\itemize{
|
||||
\item{ \code{objective} specify the learning task and the corresponding learning objective, users can pass a self-defined function to it.
|
||||
The default objective options are below:
|
||||
\item \code{objective} specify the learning task and the corresponding learning objective, users can pass a self-defined function to it. The default objective options are below:
|
||||
\itemize{
|
||||
\item \code{reg:squarederror} Regression with squared loss (Default).
|
||||
\item{ \code{reg:squaredlogerror}: regression with squared log loss \eqn{1/2 * (log(pred + 1) - log(label + 1))^2}.
|
||||
All inputs are required to be greater than -1.
|
||||
Also, see metric rmsle for possible issue with this objective.}
|
||||
\item \code{reg:squaredlogerror}: regression with squared log loss \eqn{1/2 * (log(pred + 1) - log(label + 1))^2}. All inputs are required to be greater than -1. Also, see metric rmsle for possible issue with this objective.
|
||||
\item \code{reg:logistic} logistic regression.
|
||||
\item \code{reg:pseudohubererror}: regression with Pseudo Huber loss, a twice differentiable alternative to absolute loss.
|
||||
\item \code{binary:logistic} logistic regression for binary classification. Output probability.
|
||||
\item \code{binary:logitraw} logistic regression for binary classification, output score before logistic transformation.
|
||||
\item \code{binary:hinge}: hinge loss for binary classification. This makes predictions of 0 or 1, rather than producing probabilities.
|
||||
\item{ \code{count:poisson}: Poisson regression for count data, output mean of Poisson distribution.
|
||||
\code{max_delta_step} is set to 0.7 by default in poisson regression (used to safeguard optimization).}
|
||||
\item{ \code{survival:cox}: Cox regression for right censored survival time data (negative values are considered right censored).
|
||||
Note that predictions are returned on the hazard ratio scale (i.e., as HR = exp(marginal_prediction) in the proportional
|
||||
hazard function \code{h(t) = h0(t) * HR)}.}
|
||||
\item{ \code{survival:aft}: Accelerated failure time model for censored survival time data. See
|
||||
\href{https://xgboost.readthedocs.io/en/latest/tutorials/aft_survival_analysis.html}{Survival Analysis with Accelerated Failure Time}
|
||||
for details.}
|
||||
\item \code{count:poisson}: Poisson regression for count data, output mean of Poisson distribution. \code{max_delta_step} is set to 0.7 by default in poisson regression (used to safeguard optimization).
|
||||
\item \code{survival:cox}: Cox regression for right censored survival time data (negative values are considered right censored). Note that predictions are returned on the hazard ratio scale (i.e., as HR = exp(marginal_prediction) in the proportional hazard function \code{h(t) = h0(t) * HR)}.
|
||||
\item \code{survival:aft}: Accelerated failure time model for censored survival time data. See \href{https://xgboost.readthedocs.io/en/latest/tutorials/aft_survival_analysis.html}{Survival Analysis with Accelerated Failure Time} for details.
|
||||
\item \code{aft_loss_distribution}: Probability Density Function used by \code{survival:aft} and \code{aft-nloglik} metric.
|
||||
\item{ \code{multi:softmax} set xgboost to do multiclass classification using the softmax objective.
|
||||
Class is represented by a number and should be from 0 to \code{num_class - 1}.}
|
||||
\item{ \code{multi:softprob} same as softmax, but prediction outputs a vector of ndata * nclass elements, which can be
|
||||
further reshaped to ndata, nclass matrix. The result contains predicted probabilities of each data point belonging
|
||||
to each class.}
|
||||
\item \code{multi:softmax} set xgboost to do multiclass classification using the softmax objective. Class is represented by a number and should be from 0 to \code{num_class - 1}.
|
||||
\item \code{multi:softprob} same as softmax, but prediction outputs a vector of ndata * nclass elements, which can be further reshaped to ndata, nclass matrix. The result contains predicted probabilities of each data point belonging to each class.
|
||||
\item \code{rank:pairwise} set xgboost to do ranking task by minimizing the pairwise loss.
|
||||
\item{ \code{rank:ndcg}: Use LambdaMART to perform list-wise ranking where
|
||||
\href{https://en.wikipedia.org/wiki/Discounted_cumulative_gain}{Normalized Discounted Cumulative Gain (NDCG)} is maximized.}
|
||||
\item{ \code{rank:map}: Use LambdaMART to perform list-wise ranking where
|
||||
\href{https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)#Mean_average_precision}{Mean Average Precision (MAP)}
|
||||
is maximized.}
|
||||
\item{ \code{reg:gamma}: gamma regression with log-link.
|
||||
Output is a mean of gamma distribution.
|
||||
It might be useful, e.g., for modeling insurance claims severity, or for any outcome that might be
|
||||
\href{https://en.wikipedia.org/wiki/Gamma_distribution#Applications}{gamma-distributed}.}
|
||||
\item{ \code{reg:tweedie}: Tweedie regression with log-link.
|
||||
It might be useful, e.g., for modeling total loss in insurance, or for any outcome that might be
|
||||
\href{https://en.wikipedia.org/wiki/Tweedie_distribution#Applications}{Tweedie-distributed}.}
|
||||
\item \code{rank:ndcg}: Use LambdaMART to perform list-wise ranking where \href{https://en.wikipedia.org/wiki/Discounted_cumulative_gain}{Normalized Discounted Cumulative Gain (NDCG)} is maximized.
|
||||
\item \code{rank:map}: Use LambdaMART to perform list-wise ranking where \href{https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)#Mean_average_precision}{Mean Average Precision (MAP)} is maximized.
|
||||
\item \code{reg:gamma}: gamma regression with log-link. Output is a mean of gamma distribution. It might be useful, e.g., for modeling insurance claims severity, or for any outcome that might be \href{https://en.wikipedia.org/wiki/Gamma_distribution#Applications}{gamma-distributed}.
|
||||
\item \code{reg:tweedie}: Tweedie regression with log-link. It might be useful, e.g., for modeling total loss in insurance, or for any outcome that might be \href{https://en.wikipedia.org/wiki/Tweedie_distribution#Applications}{Tweedie-distributed}.
|
||||
}
|
||||
}
|
||||
\item \code{base_score} the initial prediction score of all instances, global bias. Default: 0.5
|
||||
\item{ \code{eval_metric} evaluation metrics for validation data.
|
||||
Users can pass a self-defined function to it.
|
||||
Default: metric will be assigned according to objective
|
||||
(rmse for regression, and error for classification, mean average precision for ranking).
|
||||
List is provided in detail section.}
|
||||
\item \code{eval_metric} evaluation metrics for validation data. Users can pass a self-defined function to it. Default: metric will be assigned according to objective(rmse for regression, and error for classification, mean average precision for ranking). List is provided in detail section.
|
||||
}}
|
||||
|
||||
\item{data}{training dataset. \code{xgb.train} accepts only an \code{xgb.DMatrix} as the input.
|
||||
@@ -267,8 +223,7 @@ The following is the list of built-in metrics for which XGBoost provides optimiz
|
||||
\item \code{merror} Multiclass classification error rate. It is calculated as \code{(# wrong cases) / (# all cases)}.
|
||||
\item \code{mae} Mean absolute error
|
||||
\item \code{mape} Mean absolute percentage error
|
||||
\item{ \code{auc} Area under the curve.
|
||||
\url{https://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.}
|
||||
\item \code{auc} Area under the curve. \url{https://en.wikipedia.org/wiki/Receiver_operating_characteristic#'Area_under_curve} for ranking evaluation.
|
||||
\item \code{aucpr} Area under the PR curve. \url{https://en.wikipedia.org/wiki/Precision_and_recall} for ranking evaluation.
|
||||
\item \code{ndcg} Normalized Discounted Cumulative Gain (for ranking task). \url{https://en.wikipedia.org/wiki/NDCG}
|
||||
}
|
||||
@@ -286,8 +241,8 @@ The following callbacks are automatically created when certain parameters are se
|
||||
data(agaricus.train, package='xgboost')
|
||||
data(agaricus.test, package='xgboost')
|
||||
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtest <- with(agaricus.test, xgb.DMatrix(data, label = label, nthread = 2))
|
||||
dtrain <- with(agaricus.train, xgb.DMatrix(data, label = label))
|
||||
dtest <- with(agaricus.test, xgb.DMatrix(data, label = label))
|
||||
watchlist <- list(train = dtrain, eval = dtest)
|
||||
|
||||
## A simple xgb.train example:
|
||||
|
||||
@@ -3,11 +3,12 @@ PKGROOT=../../
|
||||
ENABLE_STD_THREAD=1
|
||||
# _*_ mode: Makefile; _*_
|
||||
|
||||
CXX_STD = CXX17
|
||||
CXX_STD = CXX14
|
||||
|
||||
XGB_RFLAGS = -DXGBOOST_STRICT_R_MODE=1 -DDMLC_LOG_BEFORE_THROW=0\
|
||||
-DDMLC_ENABLE_STD_THREAD=$(ENABLE_STD_THREAD) -DDMLC_DISABLE_STDIN=1\
|
||||
-DDMLC_LOG_CUSTOMIZE=1
|
||||
-DDMLC_LOG_CUSTOMIZE=1 -DXGBOOST_CUSTOMIZE_LOGGER=1\
|
||||
-DRABIT_CUSTOMIZE_MSG_
|
||||
|
||||
# disable the use of thread_local for 32 bit windows:
|
||||
ifeq ($(R_OSTYPE)$(WIN),windows)
|
||||
@@ -18,88 +19,7 @@ $(foreach v, $(XGB_RFLAGS), $(warning $(v)))
|
||||
PKG_CPPFLAGS= -I$(PKGROOT)/include -I$(PKGROOT)/dmlc-core/include -I$(PKGROOT)/rabit/include -I$(PKGROOT) $(XGB_RFLAGS)
|
||||
PKG_CXXFLAGS= @OPENMP_CXXFLAGS@ @ENDIAN_FLAG@ -pthread $(CXX_VISIBILITY)
|
||||
PKG_LIBS = @OPENMP_CXXFLAGS@ @OPENMP_LIB@ @ENDIAN_FLAG@ @BACKTRACE_LIB@ -pthread
|
||||
|
||||
OBJECTS= \
|
||||
./xgboost_R.o \
|
||||
./xgboost_custom.o \
|
||||
./init.o \
|
||||
$(PKGROOT)/src/metric/metric.o \
|
||||
$(PKGROOT)/src/metric/elementwise_metric.o \
|
||||
$(PKGROOT)/src/metric/multiclass_metric.o \
|
||||
$(PKGROOT)/src/metric/rank_metric.o \
|
||||
$(PKGROOT)/src/metric/auc.o \
|
||||
$(PKGROOT)/src/metric/survival_metric.o \
|
||||
$(PKGROOT)/src/objective/objective.o \
|
||||
$(PKGROOT)/src/objective/regression_obj.o \
|
||||
$(PKGROOT)/src/objective/multiclass_obj.o \
|
||||
$(PKGROOT)/src/objective/lambdarank_obj.o \
|
||||
$(PKGROOT)/src/objective/hinge.o \
|
||||
$(PKGROOT)/src/objective/aft_obj.o \
|
||||
$(PKGROOT)/src/objective/adaptive.o \
|
||||
$(PKGROOT)/src/objective/init_estimation.o \
|
||||
$(PKGROOT)/src/objective/quantile_obj.o \
|
||||
$(PKGROOT)/src/gbm/gbm.o \
|
||||
$(PKGROOT)/src/gbm/gbtree.o \
|
||||
$(PKGROOT)/src/gbm/gbtree_model.o \
|
||||
$(PKGROOT)/src/gbm/gblinear.o \
|
||||
$(PKGROOT)/src/gbm/gblinear_model.o \
|
||||
$(PKGROOT)/src/data/simple_dmatrix.o \
|
||||
$(PKGROOT)/src/data/data.o \
|
||||
$(PKGROOT)/src/data/sparse_page_raw_format.o \
|
||||
$(PKGROOT)/src/data/ellpack_page.o \
|
||||
$(PKGROOT)/src/data/gradient_index.o \
|
||||
$(PKGROOT)/src/data/gradient_index_page_source.o \
|
||||
$(PKGROOT)/src/data/gradient_index_format.o \
|
||||
$(PKGROOT)/src/data/sparse_page_dmatrix.o \
|
||||
$(PKGROOT)/src/data/proxy_dmatrix.o \
|
||||
$(PKGROOT)/src/data/iterative_dmatrix.o \
|
||||
$(PKGROOT)/src/predictor/predictor.o \
|
||||
$(PKGROOT)/src/predictor/cpu_predictor.o \
|
||||
$(PKGROOT)/src/predictor/cpu_treeshap.o \
|
||||
$(PKGROOT)/src/tree/constraints.o \
|
||||
$(PKGROOT)/src/tree/param.o \
|
||||
$(PKGROOT)/src/tree/fit_stump.o \
|
||||
$(PKGROOT)/src/tree/tree_model.o \
|
||||
$(PKGROOT)/src/tree/tree_updater.o \
|
||||
$(PKGROOT)/src/tree/multi_target_tree_model.o \
|
||||
$(PKGROOT)/src/tree/updater_approx.o \
|
||||
$(PKGROOT)/src/tree/updater_colmaker.o \
|
||||
$(PKGROOT)/src/tree/updater_prune.o \
|
||||
$(PKGROOT)/src/tree/updater_quantile_hist.o \
|
||||
$(PKGROOT)/src/tree/updater_refresh.o \
|
||||
$(PKGROOT)/src/tree/updater_sync.o \
|
||||
$(PKGROOT)/src/linear/linear_updater.o \
|
||||
$(PKGROOT)/src/linear/updater_coordinate.o \
|
||||
$(PKGROOT)/src/linear/updater_shotgun.o \
|
||||
$(PKGROOT)/src/learner.o \
|
||||
$(PKGROOT)/src/context.o \
|
||||
$(PKGROOT)/src/logging.o \
|
||||
$(PKGROOT)/src/global_config.o \
|
||||
$(PKGROOT)/src/collective/communicator.o \
|
||||
$(PKGROOT)/src/collective/in_memory_communicator.o \
|
||||
$(PKGROOT)/src/collective/in_memory_handler.o \
|
||||
$(PKGROOT)/src/collective/socket.o \
|
||||
$(PKGROOT)/src/common/charconv.o \
|
||||
$(PKGROOT)/src/common/column_matrix.o \
|
||||
$(PKGROOT)/src/common/common.o \
|
||||
$(PKGROOT)/src/common/hist_util.o \
|
||||
$(PKGROOT)/src/common/host_device_vector.o \
|
||||
$(PKGROOT)/src/common/io.o \
|
||||
$(PKGROOT)/src/common/json.o \
|
||||
$(PKGROOT)/src/common/numeric.o \
|
||||
$(PKGROOT)/src/common/pseudo_huber.o \
|
||||
$(PKGROOT)/src/common/quantile.o \
|
||||
$(PKGROOT)/src/common/random.o \
|
||||
$(PKGROOT)/src/common/stats.o \
|
||||
$(PKGROOT)/src/common/survival_util.o \
|
||||
$(PKGROOT)/src/common/threading_utils.o \
|
||||
$(PKGROOT)/src/common/ranking_utils.o \
|
||||
$(PKGROOT)/src/common/quantile_loss_utils.o \
|
||||
$(PKGROOT)/src/common/timer.o \
|
||||
$(PKGROOT)/src/common/version.o \
|
||||
$(PKGROOT)/src/c_api/c_api.o \
|
||||
$(PKGROOT)/src/c_api/c_api_error.o \
|
||||
$(PKGROOT)/amalgamation/dmlc-minimum0.o \
|
||||
$(PKGROOT)/rabit/src/engine.o \
|
||||
$(PKGROOT)/rabit/src/rabit_c_api.o \
|
||||
$(PKGROOT)/rabit/src/allreduce_base.o
|
||||
OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o \
|
||||
$(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o \
|
||||
$(PKGROOT)/rabit/src/engine.o $(PKGROOT)/rabit/src/rabit_c_api.o \
|
||||
$(PKGROOT)/rabit/src/allreduce_base.o
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
# package root
|
||||
PKGROOT=../../
|
||||
PKGROOT=./
|
||||
ENABLE_STD_THREAD=0
|
||||
# _*_ mode: Makefile; _*_
|
||||
|
||||
CXX_STD = CXX17
|
||||
# This file is only used for Windows compilation from GitHub
|
||||
# It will be replaced with Makevars.in for the CRAN version
|
||||
.PHONY: all xgblib
|
||||
all: $(SHLIB)
|
||||
$(SHLIB): xgblib
|
||||
xgblib:
|
||||
cp -r ../../src .
|
||||
cp -r ../../rabit .
|
||||
cp -r ../../dmlc-core .
|
||||
cp -r ../../include .
|
||||
cp -r ../../amalgamation .
|
||||
|
||||
CXX_STD = CXX14
|
||||
|
||||
XGB_RFLAGS = -DXGBOOST_STRICT_R_MODE=1 -DDMLC_LOG_BEFORE_THROW=0\
|
||||
-DDMLC_ENABLE_STD_THREAD=$(ENABLE_STD_THREAD) -DDMLC_DISABLE_STDIN=1\
|
||||
-DDMLC_LOG_CUSTOMIZE=1
|
||||
-DDMLC_LOG_CUSTOMIZE=1 -DXGBOOST_CUSTOMIZE_LOGGER=1\
|
||||
-DRABIT_CUSTOMIZE_MSG_
|
||||
|
||||
# disable the use of thread_local for 32 bit windows:
|
||||
ifeq ($(R_OSTYPE)$(WIN),windows)
|
||||
@@ -16,90 +29,11 @@ endif
|
||||
$(foreach v, $(XGB_RFLAGS), $(warning $(v)))
|
||||
|
||||
PKG_CPPFLAGS= -I$(PKGROOT)/include -I$(PKGROOT)/dmlc-core/include -I$(PKGROOT)/rabit/include -I$(PKGROOT) $(XGB_RFLAGS)
|
||||
PKG_CXXFLAGS= $(SHLIB_OPENMP_CXXFLAGS) -DDMLC_CMAKE_LITTLE_ENDIAN=1 $(SHLIB_PTHREAD_FLAGS) $(CXX_VISIBILITY)
|
||||
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) -DDMLC_CMAKE_LITTLE_ENDIAN=1 $(SHLIB_PTHREAD_FLAGS) -lwsock32 -lws2_32
|
||||
PKG_CXXFLAGS= $(SHLIB_OPENMP_CXXFLAGS) $(SHLIB_PTHREAD_FLAGS)
|
||||
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(SHLIB_PTHREAD_FLAGS)
|
||||
OBJECTS= ./xgboost_R.o ./xgboost_custom.o ./xgboost_assert.o ./init.o \
|
||||
$(PKGROOT)/amalgamation/xgboost-all0.o $(PKGROOT)/amalgamation/dmlc-minimum0.o \
|
||||
$(PKGROOT)/rabit/src/engine.o $(PKGROOT)/rabit/src/rabit_c_api.o \
|
||||
$(PKGROOT)/rabit/src/allreduce_base.o
|
||||
|
||||
OBJECTS= \
|
||||
./xgboost_R.o \
|
||||
./xgboost_custom.o \
|
||||
./init.o \
|
||||
$(PKGROOT)/src/metric/metric.o \
|
||||
$(PKGROOT)/src/metric/elementwise_metric.o \
|
||||
$(PKGROOT)/src/metric/multiclass_metric.o \
|
||||
$(PKGROOT)/src/metric/rank_metric.o \
|
||||
$(PKGROOT)/src/metric/auc.o \
|
||||
$(PKGROOT)/src/metric/survival_metric.o \
|
||||
$(PKGROOT)/src/objective/objective.o \
|
||||
$(PKGROOT)/src/objective/regression_obj.o \
|
||||
$(PKGROOT)/src/objective/multiclass_obj.o \
|
||||
$(PKGROOT)/src/objective/lambdarank_obj.o \
|
||||
$(PKGROOT)/src/objective/hinge.o \
|
||||
$(PKGROOT)/src/objective/aft_obj.o \
|
||||
$(PKGROOT)/src/objective/adaptive.o \
|
||||
$(PKGROOT)/src/objective/init_estimation.o \
|
||||
$(PKGROOT)/src/objective/quantile_obj.o \
|
||||
$(PKGROOT)/src/gbm/gbm.o \
|
||||
$(PKGROOT)/src/gbm/gbtree.o \
|
||||
$(PKGROOT)/src/gbm/gbtree_model.o \
|
||||
$(PKGROOT)/src/gbm/gblinear.o \
|
||||
$(PKGROOT)/src/gbm/gblinear_model.o \
|
||||
$(PKGROOT)/src/data/simple_dmatrix.o \
|
||||
$(PKGROOT)/src/data/data.o \
|
||||
$(PKGROOT)/src/data/sparse_page_raw_format.o \
|
||||
$(PKGROOT)/src/data/ellpack_page.o \
|
||||
$(PKGROOT)/src/data/gradient_index.o \
|
||||
$(PKGROOT)/src/data/gradient_index_page_source.o \
|
||||
$(PKGROOT)/src/data/gradient_index_format.o \
|
||||
$(PKGROOT)/src/data/sparse_page_dmatrix.o \
|
||||
$(PKGROOT)/src/data/proxy_dmatrix.o \
|
||||
$(PKGROOT)/src/data/iterative_dmatrix.o \
|
||||
$(PKGROOT)/src/predictor/predictor.o \
|
||||
$(PKGROOT)/src/predictor/cpu_predictor.o \
|
||||
$(PKGROOT)/src/predictor/cpu_treeshap.o \
|
||||
$(PKGROOT)/src/tree/constraints.o \
|
||||
$(PKGROOT)/src/tree/param.o \
|
||||
$(PKGROOT)/src/tree/fit_stump.o \
|
||||
$(PKGROOT)/src/tree/tree_model.o \
|
||||
$(PKGROOT)/src/tree/multi_target_tree_model.o \
|
||||
$(PKGROOT)/src/tree/tree_updater.o \
|
||||
$(PKGROOT)/src/tree/updater_approx.o \
|
||||
$(PKGROOT)/src/tree/updater_colmaker.o \
|
||||
$(PKGROOT)/src/tree/updater_prune.o \
|
||||
$(PKGROOT)/src/tree/updater_quantile_hist.o \
|
||||
$(PKGROOT)/src/tree/updater_refresh.o \
|
||||
$(PKGROOT)/src/tree/updater_sync.o \
|
||||
$(PKGROOT)/src/linear/linear_updater.o \
|
||||
$(PKGROOT)/src/linear/updater_coordinate.o \
|
||||
$(PKGROOT)/src/linear/updater_shotgun.o \
|
||||
$(PKGROOT)/src/learner.o \
|
||||
$(PKGROOT)/src/context.o \
|
||||
$(PKGROOT)/src/logging.o \
|
||||
$(PKGROOT)/src/global_config.o \
|
||||
$(PKGROOT)/src/collective/communicator.o \
|
||||
$(PKGROOT)/src/collective/in_memory_communicator.o \
|
||||
$(PKGROOT)/src/collective/in_memory_handler.o \
|
||||
$(PKGROOT)/src/collective/socket.o \
|
||||
$(PKGROOT)/src/common/charconv.o \
|
||||
$(PKGROOT)/src/common/column_matrix.o \
|
||||
$(PKGROOT)/src/common/common.o \
|
||||
$(PKGROOT)/src/common/hist_util.o \
|
||||
$(PKGROOT)/src/common/host_device_vector.o \
|
||||
$(PKGROOT)/src/common/io.o \
|
||||
$(PKGROOT)/src/common/json.o \
|
||||
$(PKGROOT)/src/common/numeric.o \
|
||||
$(PKGROOT)/src/common/pseudo_huber.o \
|
||||
$(PKGROOT)/src/common/quantile.o \
|
||||
$(PKGROOT)/src/common/random.o \
|
||||
$(PKGROOT)/src/common/stats.o \
|
||||
$(PKGROOT)/src/common/survival_util.o \
|
||||
$(PKGROOT)/src/common/threading_utils.o \
|
||||
$(PKGROOT)/src/common/ranking_utils.o \
|
||||
$(PKGROOT)/src/common/quantile_loss_utils.o \
|
||||
$(PKGROOT)/src/common/timer.o \
|
||||
$(PKGROOT)/src/common/version.o \
|
||||
$(PKGROOT)/src/c_api/c_api.o \
|
||||
$(PKGROOT)/src/c_api/c_api_error.o \
|
||||
$(PKGROOT)/amalgamation/dmlc-minimum0.o \
|
||||
$(PKGROOT)/rabit/src/engine.o \
|
||||
$(PKGROOT)/rabit/src/rabit_c_api.o \
|
||||
$(PKGROOT)/rabit/src/allreduce_base.o
|
||||
$(OBJECTS) : xgblib
|
||||
|
||||
@@ -24,32 +24,30 @@ extern SEXP XGBoosterEvalOneIter_R(SEXP, SEXP, SEXP, SEXP);
|
||||
extern SEXP XGBoosterGetAttrNames_R(SEXP);
|
||||
extern SEXP XGBoosterGetAttr_R(SEXP, SEXP);
|
||||
extern SEXP XGBoosterLoadModelFromRaw_R(SEXP, SEXP);
|
||||
extern SEXP XGBoosterSaveModelToRaw_R(SEXP handle, SEXP config);
|
||||
extern SEXP XGBoosterLoadModel_R(SEXP, SEXP);
|
||||
extern SEXP XGBoosterSaveJsonConfig_R(SEXP handle);
|
||||
extern SEXP XGBoosterLoadJsonConfig_R(SEXP handle, SEXP value);
|
||||
extern SEXP XGBoosterSerializeToBuffer_R(SEXP handle);
|
||||
extern SEXP XGBoosterUnserializeFromBuffer_R(SEXP handle, SEXP raw);
|
||||
extern SEXP XGBoosterModelToRaw_R(SEXP);
|
||||
extern SEXP XGBoosterPredict_R(SEXP, SEXP, SEXP, SEXP, SEXP);
|
||||
extern SEXP XGBoosterPredictFromDMatrix_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGBoosterSaveModel_R(SEXP, SEXP);
|
||||
extern SEXP XGBoosterSetAttr_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGBoosterSetParam_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGBoosterUpdateOneIter_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGCheckNullPtr_R(SEXP);
|
||||
extern SEXP XGDMatrixCreateFromCSC_R(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
|
||||
extern SEXP XGDMatrixCreateFromCSR_R(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
|
||||
extern SEXP XGDMatrixCreateFromCSC_R(SEXP, SEXP, SEXP, SEXP);
|
||||
extern SEXP XGDMatrixCreateFromFile_R(SEXP, SEXP);
|
||||
extern SEXP XGDMatrixCreateFromMat_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGDMatrixGetInfo_R(SEXP, SEXP);
|
||||
extern SEXP XGDMatrixGetStrFeatureInfo_R(SEXP, SEXP);
|
||||
extern SEXP XGDMatrixNumCol_R(SEXP);
|
||||
extern SEXP XGDMatrixNumRow_R(SEXP);
|
||||
extern SEXP XGDMatrixSaveBinary_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGDMatrixSetInfo_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGDMatrixSetStrFeatureInfo_R(SEXP, SEXP, SEXP);
|
||||
extern SEXP XGDMatrixSliceDMatrix_R(SEXP, SEXP);
|
||||
extern SEXP XGBSetGlobalConfig_R(SEXP);
|
||||
extern SEXP XGBGetGlobalConfig_R(void);
|
||||
extern SEXP XGBGetGlobalConfig_R();
|
||||
extern SEXP XGBoosterFeatureScore_R(SEXP, SEXP);
|
||||
|
||||
static const R_CallMethodDef CallEntries[] = {
|
||||
@@ -61,29 +59,27 @@ static const R_CallMethodDef CallEntries[] = {
|
||||
{"XGBoosterGetAttrNames_R", (DL_FUNC) &XGBoosterGetAttrNames_R, 1},
|
||||
{"XGBoosterGetAttr_R", (DL_FUNC) &XGBoosterGetAttr_R, 2},
|
||||
{"XGBoosterLoadModelFromRaw_R", (DL_FUNC) &XGBoosterLoadModelFromRaw_R, 2},
|
||||
{"XGBoosterSaveModelToRaw_R", (DL_FUNC) &XGBoosterSaveModelToRaw_R, 2},
|
||||
{"XGBoosterLoadModel_R", (DL_FUNC) &XGBoosterLoadModel_R, 2},
|
||||
{"XGBoosterSaveJsonConfig_R", (DL_FUNC) &XGBoosterSaveJsonConfig_R, 1},
|
||||
{"XGBoosterLoadJsonConfig_R", (DL_FUNC) &XGBoosterLoadJsonConfig_R, 2},
|
||||
{"XGBoosterSerializeToBuffer_R", (DL_FUNC) &XGBoosterSerializeToBuffer_R, 1},
|
||||
{"XGBoosterUnserializeFromBuffer_R", (DL_FUNC) &XGBoosterUnserializeFromBuffer_R, 2},
|
||||
{"XGBoosterModelToRaw_R", (DL_FUNC) &XGBoosterModelToRaw_R, 1},
|
||||
{"XGBoosterPredict_R", (DL_FUNC) &XGBoosterPredict_R, 5},
|
||||
{"XGBoosterPredictFromDMatrix_R", (DL_FUNC) &XGBoosterPredictFromDMatrix_R, 3},
|
||||
{"XGBoosterSaveModel_R", (DL_FUNC) &XGBoosterSaveModel_R, 2},
|
||||
{"XGBoosterSetAttr_R", (DL_FUNC) &XGBoosterSetAttr_R, 3},
|
||||
{"XGBoosterSetParam_R", (DL_FUNC) &XGBoosterSetParam_R, 3},
|
||||
{"XGBoosterUpdateOneIter_R", (DL_FUNC) &XGBoosterUpdateOneIter_R, 3},
|
||||
{"XGCheckNullPtr_R", (DL_FUNC) &XGCheckNullPtr_R, 1},
|
||||
{"XGDMatrixCreateFromCSC_R", (DL_FUNC) &XGDMatrixCreateFromCSC_R, 6},
|
||||
{"XGDMatrixCreateFromCSR_R", (DL_FUNC) &XGDMatrixCreateFromCSR_R, 6},
|
||||
{"XGDMatrixCreateFromCSC_R", (DL_FUNC) &XGDMatrixCreateFromCSC_R, 4},
|
||||
{"XGDMatrixCreateFromFile_R", (DL_FUNC) &XGDMatrixCreateFromFile_R, 2},
|
||||
{"XGDMatrixCreateFromMat_R", (DL_FUNC) &XGDMatrixCreateFromMat_R, 3},
|
||||
{"XGDMatrixGetInfo_R", (DL_FUNC) &XGDMatrixGetInfo_R, 2},
|
||||
{"XGDMatrixGetStrFeatureInfo_R", (DL_FUNC) &XGDMatrixGetStrFeatureInfo_R, 2},
|
||||
{"XGDMatrixNumCol_R", (DL_FUNC) &XGDMatrixNumCol_R, 1},
|
||||
{"XGDMatrixNumRow_R", (DL_FUNC) &XGDMatrixNumRow_R, 1},
|
||||
{"XGDMatrixSaveBinary_R", (DL_FUNC) &XGDMatrixSaveBinary_R, 3},
|
||||
{"XGDMatrixSetInfo_R", (DL_FUNC) &XGDMatrixSetInfo_R, 3},
|
||||
{"XGDMatrixSetStrFeatureInfo_R", (DL_FUNC) &XGDMatrixSetStrFeatureInfo_R, 3},
|
||||
{"XGDMatrixSliceDMatrix_R", (DL_FUNC) &XGDMatrixSliceDMatrix_R, 2},
|
||||
{"XGBSetGlobalConfig_R", (DL_FUNC) &XGBSetGlobalConfig_R, 1},
|
||||
{"XGBGetGlobalConfig_R", (DL_FUNC) &XGBGetGlobalConfig_R, 0},
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
/**
|
||||
* Copyright 2014-2023 by XGBoost Contributors
|
||||
*/
|
||||
#include <dmlc/common.h>
|
||||
// Copyright (c) 2014 by Contributors
|
||||
#include <dmlc/logging.h>
|
||||
#include <dmlc/omp.h>
|
||||
#include <dmlc/common.h>
|
||||
#include <xgboost/c_api.h>
|
||||
#include <xgboost/context.h>
|
||||
#include <xgboost/data.h>
|
||||
#include <xgboost/logging.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
#include "../../src/c_api/c_api_error.h"
|
||||
#include "../../src/c_api/c_api_utils.h" // MakeSparseFromPtr
|
||||
#include "../../src/common/threading_utils.h"
|
||||
|
||||
#include "./xgboost_R.h" // Must follow other includes.
|
||||
#include "Rinternals.h"
|
||||
#include "./xgboost_R.h"
|
||||
|
||||
/*!
|
||||
* \brief macro to annotate begin of api
|
||||
@@ -46,21 +37,8 @@
|
||||
error(XGBGetLastError()); \
|
||||
}
|
||||
|
||||
using dmlc::BeginPtr;
|
||||
|
||||
xgboost::Context const *BoosterCtx(BoosterHandle handle) {
|
||||
CHECK_HANDLE();
|
||||
auto *learner = static_cast<xgboost::Learner *>(handle);
|
||||
CHECK(learner);
|
||||
return learner->Ctx();
|
||||
}
|
||||
|
||||
xgboost::Context const *DMatrixCtx(DMatrixHandle handle) {
|
||||
CHECK_HANDLE();
|
||||
auto p_m = static_cast<std::shared_ptr<xgboost::DMatrix> *>(handle);
|
||||
CHECK(p_m);
|
||||
return p_m->get()->Ctx();
|
||||
}
|
||||
using namespace dmlc;
|
||||
|
||||
XGB_DLL SEXP XGCheckNullPtr_R(SEXP handle) {
|
||||
return ScalarLogical(R_ExternalPtrAddr(handle) == NULL);
|
||||
@@ -116,15 +94,18 @@ XGB_DLL SEXP XGDMatrixCreateFromMat_R(SEXP mat, SEXP missing, SEXP n_threads) {
|
||||
din = REAL(mat);
|
||||
}
|
||||
std::vector<float> data(nrow * ncol);
|
||||
xgboost::Context ctx;
|
||||
ctx.nthread = asInteger(n_threads);
|
||||
std::int32_t threads = ctx.Threads();
|
||||
dmlc::OMPException exc;
|
||||
int32_t threads = xgboost::common::OmpGetNumThreads(asInteger(n_threads));
|
||||
|
||||
xgboost::common::ParallelFor(nrow, threads, [&](xgboost::omp_ulong i) {
|
||||
for (size_t j = 0; j < ncol; ++j) {
|
||||
data[i * ncol + j] = is_int ? static_cast<float>(iin[i + nrow * j]) : din[i + nrow * j];
|
||||
}
|
||||
});
|
||||
#pragma omp parallel for schedule(static) num_threads(threads)
|
||||
for (omp_ulong i = 0; i < nrow; ++i) {
|
||||
exc.Run([&]() {
|
||||
for (size_t j = 0; j < ncol; ++j) {
|
||||
data[i * ncol +j] = is_int ? static_cast<float>(iin[i + nrow * j]) : din[i + nrow * j];
|
||||
}
|
||||
});
|
||||
}
|
||||
exc.Rethrow();
|
||||
DMatrixHandle handle;
|
||||
CHECK_CALL(XGDMatrixCreateFromMat_omp(BeginPtr(data), nrow, ncol,
|
||||
asReal(missing), &handle, threads));
|
||||
@@ -135,78 +116,37 @@ XGB_DLL SEXP XGDMatrixCreateFromMat_R(SEXP mat, SEXP missing, SEXP n_threads) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void CreateFromSparse(SEXP indptr, SEXP indices, SEXP data, std::string *indptr_str,
|
||||
std::string *indices_str, std::string *data_str) {
|
||||
XGB_DLL SEXP XGDMatrixCreateFromCSC_R(SEXP indptr, SEXP indices, SEXP data,
|
||||
SEXP num_row) {
|
||||
SEXP ret;
|
||||
R_API_BEGIN();
|
||||
const int *p_indptr = INTEGER(indptr);
|
||||
const int *p_indices = INTEGER(indices);
|
||||
const double *p_data = REAL(data);
|
||||
size_t nindptr = static_cast<size_t>(length(indptr));
|
||||
size_t ndata = static_cast<size_t>(length(data));
|
||||
size_t nrow = static_cast<size_t>(INTEGER(num_row)[0]);
|
||||
std::vector<size_t> col_ptr_(nindptr);
|
||||
std::vector<unsigned> indices_(ndata);
|
||||
std::vector<float> data_(ndata);
|
||||
|
||||
auto nindptr = static_cast<std::size_t>(length(indptr));
|
||||
auto ndata = static_cast<std::size_t>(length(data));
|
||||
CHECK_EQ(ndata, p_indptr[nindptr - 1]);
|
||||
xgboost::detail::MakeSparseFromPtr(p_indptr, p_indices, p_data, nindptr, indptr_str, indices_str,
|
||||
data_str);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
XGB_DLL SEXP XGDMatrixCreateFromCSC_R(SEXP indptr, SEXP indices, SEXP data, SEXP num_row,
|
||||
SEXP missing, SEXP n_threads) {
|
||||
SEXP ret;
|
||||
R_API_BEGIN();
|
||||
std::int32_t threads = asInteger(n_threads);
|
||||
|
||||
using xgboost::Integer;
|
||||
using xgboost::Json;
|
||||
using xgboost::Object;
|
||||
|
||||
std::string sindptr, sindices, sdata;
|
||||
CreateFromSparse(indptr, indices, data, &sindptr, &sindices, &sdata);
|
||||
auto nrow = static_cast<std::size_t>(INTEGER(num_row)[0]);
|
||||
|
||||
for (size_t i = 0; i < nindptr; ++i) {
|
||||
col_ptr_[i] = static_cast<size_t>(p_indptr[i]);
|
||||
}
|
||||
dmlc::OMPException exc;
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (int64_t i = 0; i < static_cast<int64_t>(ndata); ++i) {
|
||||
exc.Run([&]() {
|
||||
indices_[i] = static_cast<unsigned>(p_indices[i]);
|
||||
data_[i] = static_cast<float>(p_data[i]);
|
||||
});
|
||||
}
|
||||
exc.Rethrow();
|
||||
DMatrixHandle handle;
|
||||
Json jconfig{Object{}};
|
||||
// Construct configuration
|
||||
jconfig["nthread"] = Integer{threads};
|
||||
jconfig["missing"] = xgboost::Number{asReal(missing)};
|
||||
std::string config;
|
||||
Json::Dump(jconfig, &config);
|
||||
CHECK_CALL(XGDMatrixCreateFromCSC(sindptr.c_str(), sindices.c_str(), sdata.c_str(), nrow,
|
||||
config.c_str(), &handle));
|
||||
|
||||
CHECK_CALL(XGDMatrixCreateFromCSCEx(BeginPtr(col_ptr_), BeginPtr(indices_),
|
||||
BeginPtr(data_), nindptr, ndata,
|
||||
nrow, &handle));
|
||||
ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
|
||||
|
||||
R_RegisterCFinalizerEx(ret, _DMatrixFinalizer, TRUE);
|
||||
R_API_END();
|
||||
UNPROTECT(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGDMatrixCreateFromCSR_R(SEXP indptr, SEXP indices, SEXP data, SEXP num_col,
|
||||
SEXP missing, SEXP n_threads) {
|
||||
SEXP ret;
|
||||
R_API_BEGIN();
|
||||
std::int32_t threads = asInteger(n_threads);
|
||||
|
||||
using xgboost::Integer;
|
||||
using xgboost::Json;
|
||||
using xgboost::Object;
|
||||
|
||||
std::string sindptr, sindices, sdata;
|
||||
CreateFromSparse(indptr, indices, data, &sindptr, &sindices, &sdata);
|
||||
auto ncol = static_cast<std::size_t>(INTEGER(num_col)[0]);
|
||||
|
||||
DMatrixHandle handle;
|
||||
Json jconfig{Object{}};
|
||||
// Construct configuration
|
||||
jconfig["nthread"] = Integer{threads};
|
||||
jconfig["missing"] = xgboost::Number{asReal(missing)};
|
||||
std::string config;
|
||||
Json::Dump(jconfig, &config);
|
||||
CHECK_CALL(XGDMatrixCreateFromCSR(sindptr.c_str(), sindices.c_str(), sdata.c_str(), ncol,
|
||||
config.c_str(), &handle));
|
||||
ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
|
||||
|
||||
R_RegisterCFinalizerEx(ret, _DMatrixFinalizer, TRUE);
|
||||
R_API_END();
|
||||
UNPROTECT(1);
|
||||
@@ -246,64 +186,34 @@ XGB_DLL SEXP XGDMatrixSetInfo_R(SEXP handle, SEXP field, SEXP array) {
|
||||
R_API_BEGIN();
|
||||
int len = length(array);
|
||||
const char *name = CHAR(asChar(field));
|
||||
auto ctx = DMatrixCtx(R_ExternalPtrAddr(handle));
|
||||
dmlc::OMPException exc;
|
||||
if (!strcmp("group", name)) {
|
||||
std::vector<unsigned> vec(len);
|
||||
xgboost::common::ParallelFor(len, ctx->Threads(), [&](xgboost::omp_ulong i) {
|
||||
vec[i] = static_cast<unsigned>(INTEGER(array)[i]);
|
||||
});
|
||||
CHECK_CALL(
|
||||
XGDMatrixSetUIntInfo(R_ExternalPtrAddr(handle), CHAR(asChar(field)), BeginPtr(vec), len));
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (int i = 0; i < len; ++i) {
|
||||
exc.Run([&]() {
|
||||
vec[i] = static_cast<unsigned>(INTEGER(array)[i]);
|
||||
});
|
||||
}
|
||||
exc.Rethrow();
|
||||
CHECK_CALL(XGDMatrixSetUIntInfo(R_ExternalPtrAddr(handle),
|
||||
CHAR(asChar(field)),
|
||||
BeginPtr(vec), len));
|
||||
} else {
|
||||
std::vector<float> vec(len);
|
||||
xgboost::common::ParallelFor(len, ctx->Threads(),
|
||||
[&](xgboost::omp_ulong i) { vec[i] = REAL(array)[i]; });
|
||||
CHECK_CALL(
|
||||
XGDMatrixSetFloatInfo(R_ExternalPtrAddr(handle), CHAR(asChar(field)), BeginPtr(vec), len));
|
||||
}
|
||||
R_API_END();
|
||||
return R_NilValue;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGDMatrixSetStrFeatureInfo_R(SEXP handle, SEXP field, SEXP array) {
|
||||
R_API_BEGIN();
|
||||
size_t len{0};
|
||||
if (!isNull(array)) {
|
||||
len = length(array);
|
||||
}
|
||||
|
||||
const char *name = CHAR(asChar(field));
|
||||
std::vector<std::string> str_info;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
str_info.emplace_back(CHAR(asChar(VECTOR_ELT(array, i))));
|
||||
}
|
||||
std::vector<char const*> vec(len);
|
||||
std::transform(str_info.cbegin(), str_info.cend(), vec.begin(),
|
||||
[](std::string const &str) { return str.c_str(); });
|
||||
CHECK_CALL(XGDMatrixSetStrFeatureInfo(R_ExternalPtrAddr(handle), name, vec.data(), len));
|
||||
R_API_END();
|
||||
return R_NilValue;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGDMatrixGetStrFeatureInfo_R(SEXP handle, SEXP field) {
|
||||
SEXP ret;
|
||||
R_API_BEGIN();
|
||||
char const **out_features{nullptr};
|
||||
bst_ulong len{0};
|
||||
const char *name = CHAR(asChar(field));
|
||||
XGDMatrixGetStrFeatureInfo(R_ExternalPtrAddr(handle), name, &len, &out_features);
|
||||
|
||||
if (len > 0) {
|
||||
ret = PROTECT(allocVector(STRSXP, len));
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
SET_STRING_ELT(ret, i, mkChar(out_features[i]));
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (int i = 0; i < len; ++i) {
|
||||
exc.Run([&]() {
|
||||
vec[i] = REAL(array)[i];
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ret = PROTECT(R_NilValue);
|
||||
exc.Rethrow();
|
||||
CHECK_CALL(XGDMatrixSetFloatInfo(R_ExternalPtrAddr(handle),
|
||||
CHAR(asChar(field)),
|
||||
BeginPtr(vec), len));
|
||||
}
|
||||
R_API_END();
|
||||
UNPROTECT(1);
|
||||
return ret;
|
||||
return R_NilValue;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGDMatrixGetInfo_R(SEXP handle, SEXP field) {
|
||||
@@ -311,7 +221,10 @@ XGB_DLL SEXP XGDMatrixGetInfo_R(SEXP handle, SEXP field) {
|
||||
R_API_BEGIN();
|
||||
bst_ulong olen;
|
||||
const float *res;
|
||||
CHECK_CALL(XGDMatrixGetFloatInfo(R_ExternalPtrAddr(handle), CHAR(asChar(field)), &olen, &res));
|
||||
CHECK_CALL(XGDMatrixGetFloatInfo(R_ExternalPtrAddr(handle),
|
||||
CHAR(asChar(field)),
|
||||
&olen,
|
||||
&res));
|
||||
ret = PROTECT(allocVector(REALSXP, olen));
|
||||
for (size_t i = 0; i < olen; ++i) {
|
||||
REAL(ret)[i] = res[i];
|
||||
@@ -400,11 +313,15 @@ XGB_DLL SEXP XGBoosterBoostOneIter_R(SEXP handle, SEXP dtrain, SEXP grad, SEXP h
|
||||
<< "gradient and hess must have same length";
|
||||
int len = length(grad);
|
||||
std::vector<float> tgrad(len), thess(len);
|
||||
auto ctx = BoosterCtx(R_ExternalPtrAddr(handle));
|
||||
xgboost::common::ParallelFor(len, ctx->Threads(), [&](xgboost::omp_ulong j) {
|
||||
tgrad[j] = REAL(grad)[j];
|
||||
thess[j] = REAL(hess)[j];
|
||||
});
|
||||
dmlc::OMPException exc;
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (int j = 0; j < len; ++j) {
|
||||
exc.Run([&]() {
|
||||
tgrad[j] = REAL(grad)[j];
|
||||
thess[j] = REAL(hess)[j];
|
||||
});
|
||||
}
|
||||
exc.Rethrow();
|
||||
CHECK_CALL(XGBoosterBoostOneIter(R_ExternalPtrAddr(handle),
|
||||
R_ExternalPtrAddr(dtrain),
|
||||
BeginPtr(tgrad), BeginPtr(thess),
|
||||
@@ -438,6 +355,27 @@ XGB_DLL SEXP XGBoosterEvalOneIter_R(SEXP handle, SEXP iter, SEXP dmats, SEXP evn
|
||||
return mkString(ret);
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGBoosterPredict_R(SEXP handle, SEXP dmat, SEXP option_mask,
|
||||
SEXP ntree_limit, SEXP training) {
|
||||
SEXP ret;
|
||||
R_API_BEGIN();
|
||||
bst_ulong olen;
|
||||
const float *res;
|
||||
CHECK_CALL(XGBoosterPredict(R_ExternalPtrAddr(handle),
|
||||
R_ExternalPtrAddr(dmat),
|
||||
asInteger(option_mask),
|
||||
asInteger(ntree_limit),
|
||||
asInteger(training),
|
||||
&olen, &res));
|
||||
ret = PROTECT(allocVector(REALSXP, olen));
|
||||
for (size_t i = 0; i < olen; ++i) {
|
||||
REAL(ret)[i] = res[i];
|
||||
}
|
||||
R_API_END();
|
||||
UNPROTECT(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGBoosterPredictFromDMatrix_R(SEXP handle, SEXP dmat, SEXP json_config) {
|
||||
SEXP r_out_shape;
|
||||
SEXP r_out_result;
|
||||
@@ -460,10 +398,11 @@ XGB_DLL SEXP XGBoosterPredictFromDMatrix_R(SEXP handle, SEXP dmat, SEXP json_con
|
||||
len *= out_shape[i];
|
||||
}
|
||||
r_out_result = PROTECT(allocVector(REALSXP, len));
|
||||
auto ctx = BoosterCtx(R_ExternalPtrAddr(handle));
|
||||
xgboost::common::ParallelFor(len, ctx->Threads(), [&](xgboost::omp_ulong i) {
|
||||
|
||||
#pragma omp parallel for
|
||||
for (omp_ulong i = 0; i < len; ++i) {
|
||||
REAL(r_out_result)[i] = out_result[i];
|
||||
});
|
||||
}
|
||||
|
||||
r_out = PROTECT(allocVector(VECSXP, 2));
|
||||
|
||||
@@ -490,6 +429,21 @@ XGB_DLL SEXP XGBoosterSaveModel_R(SEXP handle, SEXP fname) {
|
||||
return R_NilValue;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGBoosterModelToRaw_R(SEXP handle) {
|
||||
SEXP ret;
|
||||
R_API_BEGIN();
|
||||
bst_ulong olen;
|
||||
const char *raw;
|
||||
CHECK_CALL(XGBoosterGetModelRaw(R_ExternalPtrAddr(handle), &olen, &raw));
|
||||
ret = PROTECT(allocVector(RAWSXP, olen));
|
||||
if (olen != 0) {
|
||||
memcpy(RAW(ret), raw, olen);
|
||||
}
|
||||
R_API_END();
|
||||
UNPROTECT(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGBoosterLoadModelFromRaw_R(SEXP handle, SEXP raw) {
|
||||
R_API_BEGIN();
|
||||
CHECK_CALL(XGBoosterLoadModelFromBuffer(R_ExternalPtrAddr(handle),
|
||||
@@ -499,22 +453,6 @@ XGB_DLL SEXP XGBoosterLoadModelFromRaw_R(SEXP handle, SEXP raw) {
|
||||
return R_NilValue;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGBoosterSaveModelToRaw_R(SEXP handle, SEXP json_config) {
|
||||
SEXP ret;
|
||||
R_API_BEGIN();
|
||||
bst_ulong olen;
|
||||
char const *c_json_config = CHAR(asChar(json_config));
|
||||
char const *raw;
|
||||
CHECK_CALL(XGBoosterSaveModelToBuffer(R_ExternalPtrAddr(handle), c_json_config, &olen, &raw))
|
||||
ret = PROTECT(allocVector(RAWSXP, olen));
|
||||
if (olen != 0) {
|
||||
std::memcpy(RAW(ret), raw, olen);
|
||||
}
|
||||
R_API_END();
|
||||
UNPROTECT(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
XGB_DLL SEXP XGBoosterSaveJsonConfig_R(SEXP handle) {
|
||||
const char* ret;
|
||||
R_API_BEGIN();
|
||||
@@ -661,6 +599,7 @@ XGB_DLL SEXP XGBoosterFeatureScore_R(SEXP handle, SEXP json_config) {
|
||||
CHECK_CALL(XGBoosterFeatureScore(R_ExternalPtrAddr(handle), c_json_config,
|
||||
&out_n_features, &out_features,
|
||||
&out_dim, &out_shape, &out_scores));
|
||||
|
||||
out_shape_sexp = PROTECT(allocVector(INTSXP, out_dim));
|
||||
size_t len = 1;
|
||||
for (size_t i = 0; i < out_dim; ++i) {
|
||||
@@ -669,10 +608,10 @@ XGB_DLL SEXP XGBoosterFeatureScore_R(SEXP handle, SEXP json_config) {
|
||||
}
|
||||
|
||||
out_scores_sexp = PROTECT(allocVector(REALSXP, len));
|
||||
auto ctx = BoosterCtx(R_ExternalPtrAddr(handle));
|
||||
xgboost::common::ParallelFor(len, ctx->Threads(), [&](xgboost::omp_ulong i) {
|
||||
#pragma omp parallel for
|
||||
for (omp_ulong i = 0; i < len; ++i) {
|
||||
REAL(out_scores_sexp)[i] = out_scores[i];
|
||||
});
|
||||
}
|
||||
|
||||
out_features_sexp = PROTECT(allocVector(STRSXP, out_n_features));
|
||||
for (size_t i = 0; i < out_n_features; ++i) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright 2014-2022 by XGBoost Contributors
|
||||
* Copyright 2014 (c) by Contributors
|
||||
* \file xgboost_R.h
|
||||
* \author Tianqi Chen
|
||||
* \brief R wrapper of xgboost
|
||||
@@ -59,25 +59,12 @@ XGB_DLL SEXP XGDMatrixCreateFromMat_R(SEXP mat,
|
||||
* \param indices row indices
|
||||
* \param data content of the data
|
||||
* \param num_row numer of rows (when it's set to 0, then guess from data)
|
||||
* \param missing which value to represent missing value
|
||||
* \param n_threads Number of threads used to construct DMatrix from csc matrix.
|
||||
* \return created dmatrix
|
||||
*/
|
||||
XGB_DLL SEXP XGDMatrixCreateFromCSC_R(SEXP indptr, SEXP indices, SEXP data, SEXP num_row,
|
||||
SEXP missing, SEXP n_threads);
|
||||
|
||||
/*!
|
||||
* \brief create a matrix content from CSR format
|
||||
* \param indptr pointer to row headers
|
||||
* \param indices column indices
|
||||
* \param data content of the data
|
||||
* \param num_col numer of columns (when it's set to 0, then guess from data)
|
||||
* \param missing which value to represent missing value
|
||||
* \param n_threads Number of threads used to construct DMatrix from csr matrix.
|
||||
* \return created dmatrix
|
||||
*/
|
||||
XGB_DLL SEXP XGDMatrixCreateFromCSR_R(SEXP indptr, SEXP indices, SEXP data, SEXP num_col,
|
||||
SEXP missing, SEXP n_threads);
|
||||
XGB_DLL SEXP XGDMatrixCreateFromCSC_R(SEXP indptr,
|
||||
SEXP indices,
|
||||
SEXP data,
|
||||
SEXP num_row);
|
||||
|
||||
/*!
|
||||
* \brief create a new dmatrix from sliced content of existing matrix
|
||||
@@ -178,6 +165,17 @@ XGB_DLL SEXP XGBoosterBoostOneIter_R(SEXP handle, SEXP dtrain, SEXP grad, SEXP h
|
||||
*/
|
||||
XGB_DLL SEXP XGBoosterEvalOneIter_R(SEXP handle, SEXP iter, SEXP dmats, SEXP evnames);
|
||||
|
||||
/*!
|
||||
* \brief (Deprecated) make prediction based on dmat
|
||||
* \param handle handle
|
||||
* \param dmat data matrix
|
||||
* \param option_mask output_margin:1 predict_leaf:2
|
||||
* \param ntree_limit limit number of trees used in prediction
|
||||
* \param training Whether the prediction value is used for training.
|
||||
*/
|
||||
XGB_DLL SEXP XGBoosterPredict_R(SEXP handle, SEXP dmat, SEXP option_mask,
|
||||
SEXP ntree_limit, SEXP training);
|
||||
|
||||
/*!
|
||||
* \brief Run prediction on DMatrix, replacing `XGBoosterPredict_R`
|
||||
* \param handle handle
|
||||
@@ -211,21 +209,11 @@ XGB_DLL SEXP XGBoosterSaveModel_R(SEXP handle, SEXP fname);
|
||||
XGB_DLL SEXP XGBoosterLoadModelFromRaw_R(SEXP handle, SEXP raw);
|
||||
|
||||
/*!
|
||||
* \brief Save model into R's raw array
|
||||
*
|
||||
* \brief save model into R's raw array
|
||||
* \param handle handle
|
||||
* \param json_config JSON encoded string storing parameters for the function. Following
|
||||
* keys are expected in the JSON document:
|
||||
*
|
||||
* "format": str
|
||||
* - json: Output booster will be encoded as JSON.
|
||||
* - ubj: Output booster will be encoded as Univeral binary JSON.
|
||||
* - deprecated: Output booster will be encoded as old custom binary format. Do now use
|
||||
* this format except for compatibility reasons.
|
||||
*
|
||||
* \return Raw array
|
||||
* \return raw array
|
||||
*/
|
||||
XGB_DLL SEXP XGBoosterSaveModelToRaw_R(SEXP handle, SEXP json_config);
|
||||
XGB_DLL SEXP XGBoosterModelToRaw_R(SEXP handle);
|
||||
|
||||
/*!
|
||||
* \brief Save internal parameters as a JSON string
|
||||
|
||||
26
R-package/src/xgboost_assert.c
Normal file
26
R-package/src/xgboost_assert.c
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2014 by Contributors
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <Rinternals.h>
|
||||
|
||||
// implements error handling
|
||||
void XGBoostAssert_R(int exp, const char *fmt, ...) {
|
||||
char buf[1024];
|
||||
if (exp == 0) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
error("AssertError:%s\n", buf);
|
||||
}
|
||||
}
|
||||
void XGBoostCheck_R(int exp, const char *fmt, ...) {
|
||||
char buf[1024];
|
||||
if (exp == 0) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
error("%s\n", buf);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
## Install dependencies of R package for testing. The list might not be
|
||||
## up-to-date, check DESCRIPTION for the latest list and update this one if
|
||||
## inconsistent is found.
|
||||
pkgs <- c(
|
||||
## CI
|
||||
"caret",
|
||||
"pkgbuild",
|
||||
"roxygen2",
|
||||
"XML",
|
||||
"cplm",
|
||||
"e1071",
|
||||
## suggests
|
||||
"knitr",
|
||||
"rmarkdown",
|
||||
"ggplot2",
|
||||
"DiagrammeR",
|
||||
"Ckmeans.1d.dp",
|
||||
"vcd",
|
||||
"lintr",
|
||||
"testthat",
|
||||
"igraph",
|
||||
"float",
|
||||
"titanic",
|
||||
## imports
|
||||
"Matrix",
|
||||
"methods",
|
||||
"data.table",
|
||||
"jsonlite"
|
||||
)
|
||||
|
||||
ncpus <- parallel::detectCores()
|
||||
print(paste0("Using ", ncpus, " cores to install dependencies."))
|
||||
|
||||
if (.Platform$OS.type == "unix") {
|
||||
print("Installing source packages on unix.")
|
||||
install.packages(
|
||||
pkgs,
|
||||
repo = "https://cloud.r-project.org",
|
||||
dependencies = c("Depends", "Imports", "LinkingTo"),
|
||||
Ncpus = parallel::detectCores()
|
||||
)
|
||||
} else {
|
||||
print("Installing binary packages on Windows.")
|
||||
install.packages(
|
||||
pkgs,
|
||||
repo = "https://cloud.r-project.org",
|
||||
dependencies = c("Depends", "Imports", "LinkingTo"),
|
||||
Ncpus = parallel::detectCores(),
|
||||
type = "binary"
|
||||
)
|
||||
}
|
||||
71
R-package/tests/helper_scripts/run_lint.R
Normal file
71
R-package/tests/helper_scripts/run_lint.R
Normal file
@@ -0,0 +1,71 @@
|
||||
library(lintr)
|
||||
library(crayon)
|
||||
|
||||
my_linters <- list(
|
||||
absolute_path_linter = lintr::absolute_path_linter,
|
||||
assignment_linter = lintr::assignment_linter,
|
||||
closed_curly_linter = lintr::closed_curly_linter,
|
||||
commas_linter = lintr::commas_linter,
|
||||
equals_na = lintr::equals_na_linter,
|
||||
infix_spaces_linter = lintr::infix_spaces_linter,
|
||||
line_length_linter = lintr::line_length_linter,
|
||||
no_tab_linter = lintr::no_tab_linter,
|
||||
object_usage_linter = lintr::object_usage_linter,
|
||||
object_length_linter = lintr::object_length_linter,
|
||||
open_curly_linter = lintr::open_curly_linter,
|
||||
semicolon = lintr::semicolon_terminator_linter,
|
||||
seq = lintr::seq_linter,
|
||||
spaces_inside_linter = lintr::spaces_inside_linter,
|
||||
spaces_left_parentheses_linter = lintr::spaces_left_parentheses_linter,
|
||||
trailing_blank_lines_linter = lintr::trailing_blank_lines_linter,
|
||||
trailing_whitespace_linter = lintr::trailing_whitespace_linter,
|
||||
true_false = lintr::T_and_F_symbol_linter,
|
||||
unneeded_concatenation = lintr::unneeded_concatenation_linter
|
||||
)
|
||||
|
||||
results <- lapply(
|
||||
list.files(path = '.', pattern = '\\.[Rr]$', recursive = TRUE),
|
||||
function (r_file) {
|
||||
cat(sprintf("Processing %s ...\n", r_file))
|
||||
list(r_file = r_file,
|
||||
output = lintr::lint(filename = r_file, linters = my_linters))
|
||||
})
|
||||
num_issue <- Reduce(sum, lapply(results, function (e) length(e$output)))
|
||||
|
||||
lint2str <- function(lint_entry) {
|
||||
color <- function(type) {
|
||||
switch(type,
|
||||
"warning" = crayon::magenta,
|
||||
"error" = crayon::red,
|
||||
"style" = crayon::blue,
|
||||
crayon::bold
|
||||
)
|
||||
}
|
||||
|
||||
paste0(
|
||||
lapply(lint_entry$output,
|
||||
function (lint_line) {
|
||||
paste0(
|
||||
crayon::bold(lint_entry$r_file, ":",
|
||||
as.character(lint_line$line_number), ":",
|
||||
as.character(lint_line$column_number), ": ", sep = ""),
|
||||
color(lint_line$type)(lint_line$type, ": ", sep = ""),
|
||||
crayon::bold(lint_line$message), "\n",
|
||||
lint_line$line, "\n",
|
||||
lintr:::highlight_string(lint_line$message, lint_line$column_number, lint_line$ranges),
|
||||
"\n",
|
||||
collapse = "")
|
||||
}),
|
||||
collapse = "")
|
||||
}
|
||||
|
||||
if (num_issue > 0) {
|
||||
cat(sprintf('R linters found %d issues:\n', num_issue))
|
||||
for (entry in results) {
|
||||
if (length(entry$output)) {
|
||||
cat(paste0('**** ', crayon::bold(entry$r_file), '\n'))
|
||||
cat(paste0(lint2str(entry), collapse = ''))
|
||||
}
|
||||
}
|
||||
quit(save = 'no', status = 1) # Signal error to parent shell
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
require(xgboost)
|
||||
|
||||
context("basic functions")
|
||||
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
@@ -85,18 +87,9 @@ test_that("dart prediction works", {
|
||||
rnorm(100)
|
||||
|
||||
set.seed(1994)
|
||||
booster_by_xgboost <- xgboost(
|
||||
data = d,
|
||||
label = y,
|
||||
max_depth = 2,
|
||||
booster = "dart",
|
||||
rate_drop = 0.5,
|
||||
one_drop = TRUE,
|
||||
eta = 1,
|
||||
nthread = 2,
|
||||
nrounds = nrounds,
|
||||
objective = "reg:squarederror"
|
||||
)
|
||||
booster_by_xgboost <- xgboost(data = d, label = y, max_depth = 2, booster = "dart",
|
||||
rate_drop = 0.5, one_drop = TRUE,
|
||||
eta = 1, nthread = 2, nrounds = nrounds, objective = "reg:squarederror")
|
||||
pred_by_xgboost_0 <- predict(booster_by_xgboost, newdata = d, ntreelimit = 0)
|
||||
pred_by_xgboost_1 <- predict(booster_by_xgboost, newdata = d, ntreelimit = nrounds)
|
||||
expect_true(all(matrix(pred_by_xgboost_0, byrow = TRUE) == matrix(pred_by_xgboost_1, byrow = TRUE)))
|
||||
@@ -106,19 +99,19 @@ test_that("dart prediction works", {
|
||||
|
||||
set.seed(1994)
|
||||
dtrain <- xgb.DMatrix(data = d, info = list(label = y))
|
||||
booster_by_train <- xgb.train(
|
||||
params = list(
|
||||
booster = "dart",
|
||||
max_depth = 2,
|
||||
eta = 1,
|
||||
rate_drop = 0.5,
|
||||
one_drop = TRUE,
|
||||
nthread = 1,
|
||||
objective = "reg:squarederror"
|
||||
),
|
||||
data = dtrain,
|
||||
nrounds = nrounds
|
||||
)
|
||||
booster_by_train <- xgb.train(params = list(
|
||||
booster = "dart",
|
||||
max_depth = 2,
|
||||
eta = 1,
|
||||
rate_drop = 0.5,
|
||||
one_drop = TRUE,
|
||||
nthread = 1,
|
||||
tree_method = "exact",
|
||||
objective = "reg:squarederror"
|
||||
),
|
||||
data = dtrain,
|
||||
nrounds = nrounds
|
||||
)
|
||||
pred_by_train_0 <- predict(booster_by_train, newdata = dtrain, ntreelimit = 0)
|
||||
pred_by_train_1 <- predict(booster_by_train, newdata = dtrain, ntreelimit = nrounds)
|
||||
pred_by_train_2 <- predict(booster_by_train, newdata = dtrain, training = TRUE)
|
||||
@@ -241,20 +234,12 @@ test_that("train and predict RF with softprob", {
|
||||
test_that("use of multiple eval metrics works", {
|
||||
expect_output(
|
||||
bst <- xgboost(data = train$data, label = train$label, max_depth = 2,
|
||||
eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic",
|
||||
eval_metric = 'error', eval_metric = 'auc', eval_metric = "logloss")
|
||||
eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic",
|
||||
eval_metric = 'error', eval_metric = 'auc', eval_metric = "logloss")
|
||||
, "train-error.*train-auc.*train-logloss")
|
||||
expect_false(is.null(bst$evaluation_log))
|
||||
expect_equal(dim(bst$evaluation_log), c(2, 4))
|
||||
expect_equal(colnames(bst$evaluation_log), c("iter", "train_error", "train_auc", "train_logloss"))
|
||||
expect_output(
|
||||
bst2 <- xgboost(data = train$data, label = train$label, max_depth = 2,
|
||||
eta = 1, nthread = 2, nrounds = 2, objective = "binary:logistic",
|
||||
eval_metric = list("error", "auc", "logloss"))
|
||||
, "train-error.*train-auc.*train-logloss")
|
||||
expect_false(is.null(bst2$evaluation_log))
|
||||
expect_equal(dim(bst2$evaluation_log), c(2, 4))
|
||||
expect_equal(colnames(bst2$evaluation_log), c("iter", "train_error", "train_auc", "train_logloss"))
|
||||
})
|
||||
|
||||
|
||||
@@ -408,7 +393,7 @@ test_that("colsample_bytree works", {
|
||||
xgb.importance(model = bst)
|
||||
# If colsample_bytree works properly, a variety of features should be used
|
||||
# in the 100 trees
|
||||
expect_gte(nrow(xgb.importance(model = bst)), 28)
|
||||
expect_gte(nrow(xgb.importance(model = bst)), 30)
|
||||
})
|
||||
|
||||
test_that("Configuration works", {
|
||||
@@ -418,7 +403,7 @@ test_that("Configuration works", {
|
||||
config <- xgb.config(bst)
|
||||
xgb.config(bst) <- config
|
||||
reloaded_config <- xgb.config(bst)
|
||||
expect_equal(config, reloaded_config)
|
||||
expect_equal(config, reloaded_config);
|
||||
})
|
||||
|
||||
test_that("strict_shape works", {
|
||||
@@ -474,18 +459,3 @@ test_that("strict_shape works", {
|
||||
test_iris()
|
||||
test_agaricus()
|
||||
})
|
||||
|
||||
test_that("'predict' accepts CSR data", {
|
||||
X <- agaricus.train$data
|
||||
y <- agaricus.train$label
|
||||
x_csc <- as(X[1L, , drop = FALSE], "CsparseMatrix")
|
||||
x_csr <- as(x_csc, "RsparseMatrix")
|
||||
x_spv <- as(x_csc, "sparseVector")
|
||||
bst <- xgboost(data = X, label = y, objective = "binary:logistic",
|
||||
nrounds = 5L, verbose = FALSE)
|
||||
p_csc <- predict(bst, x_csc)
|
||||
p_csr <- predict(bst, x_csr)
|
||||
p_spv <- predict(bst, x_spv)
|
||||
expect_equal(p_csc, p_csr)
|
||||
expect_equal(p_csc, p_spv)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
# More specific testing of callbacks
|
||||
|
||||
require(xgboost)
|
||||
require(data.table)
|
||||
require(titanic)
|
||||
|
||||
context("callbacks")
|
||||
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
@@ -79,7 +84,7 @@ test_that("cb.evaluation.log works as expected", {
|
||||
list(c(iter = 1, bst_evaluation), c(iter = 2, bst_evaluation)))
|
||||
expect_silent(f(finalize = TRUE))
|
||||
expect_equal(evaluation_log,
|
||||
data.table::data.table(iter = 1:2, train_auc = c(0.9, 0.9), test_auc = c(0.8, 0.8)))
|
||||
data.table(iter = 1:2, train_auc = c(0.9, 0.9), test_auc = c(0.8, 0.8)))
|
||||
|
||||
bst_evaluation_err <- c('train-auc' = 0.1, 'test-auc' = 0.2)
|
||||
evaluation_log <- list()
|
||||
@@ -96,7 +101,7 @@ test_that("cb.evaluation.log works as expected", {
|
||||
c(iter = 2, c(bst_evaluation, bst_evaluation_err))))
|
||||
expect_silent(f(finalize = TRUE))
|
||||
expect_equal(evaluation_log,
|
||||
data.table::data.table(iter = 1:2,
|
||||
data.table(iter = 1:2,
|
||||
train_auc_mean = c(0.9, 0.9), train_auc_std = c(0.1, 0.1),
|
||||
test_auc_mean = c(0.8, 0.8), test_auc_std = c(0.2, 0.2)))
|
||||
})
|
||||
@@ -251,9 +256,6 @@ test_that("early stopping using a specific metric works", {
|
||||
})
|
||||
|
||||
test_that("early stopping works with titanic", {
|
||||
if (!requireNamespace("titanic")) {
|
||||
testthat::skip("Optional testing dependency 'titanic' not found.")
|
||||
}
|
||||
# This test was inspired by https://github.com/dmlc/xgboost/issues/5935
|
||||
# It catches possible issues on noLD R
|
||||
titanic <- titanic::titanic_train
|
||||
@@ -320,7 +322,7 @@ test_that("prediction in early-stopping xgb.cv works", {
|
||||
expect_output(
|
||||
cv <- xgb.cv(param, dtrain, nfold = 5, eta = 0.1, nrounds = 20,
|
||||
early_stopping_rounds = 5, maximize = FALSE, stratified = FALSE,
|
||||
prediction = TRUE, base_score = 0.5)
|
||||
prediction = TRUE)
|
||||
, "Stopping. Best iteration")
|
||||
|
||||
expect_false(is.null(cv$best_iteration))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
context('Test models with custom objective')
|
||||
|
||||
require(xgboost)
|
||||
|
||||
set.seed(1994)
|
||||
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
library(Matrix)
|
||||
require(xgboost)
|
||||
require(Matrix)
|
||||
|
||||
context("testing xgb.DMatrix functionality")
|
||||
|
||||
data(agaricus.test, package = "xgboost")
|
||||
data(agaricus.test, package = 'xgboost')
|
||||
test_data <- agaricus.test$data[1:100, ]
|
||||
test_label <- agaricus.test$label[1:100]
|
||||
|
||||
@@ -11,56 +13,20 @@ test_that("xgb.DMatrix: basic construction", {
|
||||
|
||||
# from dense matrix
|
||||
dtest2 <- xgb.DMatrix(as.matrix(test_data), label = test_label)
|
||||
expect_equal(getinfo(dtest1, "label"), getinfo(dtest2, "label"))
|
||||
expect_equal(getinfo(dtest1, 'label'), getinfo(dtest2, 'label'))
|
||||
expect_equal(dim(dtest1), dim(dtest2))
|
||||
|
||||
# from dense integer matrix
|
||||
#from dense integer matrix
|
||||
int_data <- as.matrix(test_data)
|
||||
storage.mode(int_data) <- "integer"
|
||||
dtest3 <- xgb.DMatrix(int_data, label = test_label)
|
||||
expect_equal(dim(dtest1), dim(dtest3))
|
||||
|
||||
n_samples <- 100
|
||||
X <- cbind(
|
||||
x1 = sample(x = 4, size = n_samples, replace = TRUE),
|
||||
x2 = sample(x = 4, size = n_samples, replace = TRUE),
|
||||
x3 = sample(x = 4, size = n_samples, replace = TRUE)
|
||||
)
|
||||
X <- matrix(X, nrow = n_samples)
|
||||
y <- rbinom(n = n_samples, size = 1, prob = 1 / 2)
|
||||
|
||||
fd <- xgb.DMatrix(X, label = y, missing = 1)
|
||||
|
||||
dgc <- as(X, "dgCMatrix")
|
||||
fdgc <- xgb.DMatrix(dgc, label = y, missing = 1.0)
|
||||
|
||||
dgr <- as(X, "dgRMatrix")
|
||||
fdgr <- xgb.DMatrix(dgr, label = y, missing = 1)
|
||||
|
||||
params <- list(tree_method = "hist")
|
||||
bst_fd <- xgb.train(
|
||||
params, nrounds = 8, fd, watchlist = list(train = fd)
|
||||
)
|
||||
bst_dgr <- xgb.train(
|
||||
params, nrounds = 8, fdgr, watchlist = list(train = fdgr)
|
||||
)
|
||||
bst_dgc <- xgb.train(
|
||||
params, nrounds = 8, fdgc, watchlist = list(train = fdgc)
|
||||
)
|
||||
|
||||
raw_fd <- xgb.save.raw(bst_fd, raw_format = "ubj")
|
||||
raw_dgr <- xgb.save.raw(bst_dgr, raw_format = "ubj")
|
||||
raw_dgc <- xgb.save.raw(bst_dgc, raw_format = "ubj")
|
||||
|
||||
expect_equal(raw_fd, raw_dgr)
|
||||
expect_equal(raw_fd, raw_dgc)
|
||||
})
|
||||
|
||||
test_that("xgb.DMatrix: saving, loading", {
|
||||
# save to a local file
|
||||
dtest1 <- xgb.DMatrix(test_data, label = test_label)
|
||||
tmp_file <- tempfile('xgb.DMatrix_')
|
||||
on.exit(unlink(tmp_file))
|
||||
expect_true(xgb.DMatrix.save(dtest1, tmp_file))
|
||||
# read from a local file
|
||||
expect_output(dtest3 <- xgb.DMatrix(tmp_file), "entries loaded from")
|
||||
@@ -70,25 +36,12 @@ test_that("xgb.DMatrix: saving, loading", {
|
||||
|
||||
# from a libsvm text file
|
||||
tmp <- c("0 1:1 2:1", "1 3:1", "0 1:1")
|
||||
tmp_file <- tempfile(fileext = ".libsvm")
|
||||
tmp_file <- 'tmp.libsvm'
|
||||
writeLines(tmp, tmp_file)
|
||||
dtest4 <- xgb.DMatrix(paste(tmp_file, "?format=libsvm", sep = ""), silent = TRUE)
|
||||
dtest4 <- xgb.DMatrix(tmp_file, silent = TRUE)
|
||||
expect_equal(dim(dtest4), c(3, 4))
|
||||
expect_equal(getinfo(dtest4, 'label'), c(0, 1, 0))
|
||||
|
||||
# check that feature info is saved
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
dtrain <- xgb.DMatrix(data = agaricus.train$data, label = agaricus.train$label)
|
||||
cnames <- colnames(dtrain)
|
||||
expect_equal(length(cnames), 126)
|
||||
tmp_file <- tempfile('xgb.DMatrix_')
|
||||
xgb.DMatrix.save(dtrain, tmp_file)
|
||||
dtrain <- xgb.DMatrix(tmp_file)
|
||||
expect_equal(colnames(dtrain), cnames)
|
||||
|
||||
ft <- rep(c("c", "q"), each = length(cnames) / 2)
|
||||
setinfo(dtrain, "feature_type", ft)
|
||||
expect_equal(ft, getinfo(dtrain, "feature_type"))
|
||||
unlink(tmp_file)
|
||||
})
|
||||
|
||||
test_that("xgb.DMatrix: getinfo & setinfo", {
|
||||
@@ -156,62 +109,9 @@ test_that("xgb.DMatrix: colnames", {
|
||||
test_that("xgb.DMatrix: nrow is correct for a very sparse matrix", {
|
||||
set.seed(123)
|
||||
nr <- 1000
|
||||
x <- Matrix::rsparsematrix(nr, 100, density = 0.0005)
|
||||
x <- rsparsematrix(nr, 100, density = 0.0005)
|
||||
# we want it very sparse, so that last rows are empty
|
||||
expect_lt(max(x@i), nr)
|
||||
dtest <- xgb.DMatrix(x)
|
||||
expect_equal(dim(dtest), dim(x))
|
||||
})
|
||||
|
||||
test_that("xgb.DMatrix: print", {
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
|
||||
# core DMatrix with just data and labels
|
||||
dtrain <- xgb.DMatrix(
|
||||
data = agaricus.train$data
|
||||
, label = agaricus.train$label
|
||||
)
|
||||
txt <- capture.output({
|
||||
print(dtrain)
|
||||
})
|
||||
expect_equal(txt, "xgb.DMatrix dim: 6513 x 126 info: label colnames: yes")
|
||||
|
||||
# verbose=TRUE prints feature names
|
||||
txt <- capture.output({
|
||||
print(dtrain, verbose = TRUE)
|
||||
})
|
||||
expect_equal(txt[[1L]], "xgb.DMatrix dim: 6513 x 126 info: label colnames:")
|
||||
expect_equal(txt[[2L]], sprintf("'%s'", paste(colnames(dtrain), collapse = "','")))
|
||||
|
||||
# DMatrix with weights and base_margin
|
||||
dtrain <- xgb.DMatrix(
|
||||
data = agaricus.train$data
|
||||
, label = agaricus.train$label
|
||||
, weight = seq_along(agaricus.train$label)
|
||||
, base_margin = agaricus.train$label
|
||||
)
|
||||
txt <- capture.output({
|
||||
print(dtrain)
|
||||
})
|
||||
expect_equal(txt, "xgb.DMatrix dim: 6513 x 126 info: label weight base_margin colnames: yes")
|
||||
|
||||
# DMatrix with just features
|
||||
dtrain <- xgb.DMatrix(
|
||||
data = agaricus.train$data
|
||||
)
|
||||
txt <- capture.output({
|
||||
print(dtrain)
|
||||
})
|
||||
expect_equal(txt, "xgb.DMatrix dim: 6513 x 126 info: NA colnames: yes")
|
||||
|
||||
# DMatrix with no column names
|
||||
data_no_colnames <- agaricus.train$data
|
||||
colnames(data_no_colnames) <- NULL
|
||||
dtrain <- xgb.DMatrix(
|
||||
data = data_no_colnames
|
||||
)
|
||||
txt <- capture.output({
|
||||
print(dtrain)
|
||||
})
|
||||
expect_equal(txt, "xgb.DMatrix dim: 6513 x 126 info: NA colnames: no")
|
||||
})
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
context("feature weights")
|
||||
|
||||
test_that("training with feature weights works", {
|
||||
nrows <- 1000
|
||||
ncols <- 9
|
||||
set.seed(2022)
|
||||
x <- matrix(rnorm(nrows * ncols), nrow = nrows)
|
||||
y <- rowSums(x)
|
||||
weights <- seq(from = 1, to = ncols)
|
||||
|
||||
test <- function(tm) {
|
||||
names <- paste0("f", 1:ncols)
|
||||
xy <- xgb.DMatrix(data = x, label = y, feature_weights = weights)
|
||||
params <- list(colsample_bynode = 0.4, tree_method = tm, nthread = 1)
|
||||
model <- xgb.train(params = params, data = xy, nrounds = 32)
|
||||
importance <- xgb.importance(model = model, feature_names = names)
|
||||
expect_equal(dim(importance), c(ncols, 4))
|
||||
importance <- importance[order(importance$Feature)]
|
||||
expect_lt(importance[1, Frequency], importance[9, Frequency])
|
||||
}
|
||||
|
||||
for (tm in c("hist", "approx", "exact")) {
|
||||
test(tm)
|
||||
}
|
||||
})
|
||||
@@ -1,3 +1,5 @@
|
||||
require(xgboost)
|
||||
|
||||
context("Garbage Collection Safety Check")
|
||||
|
||||
test_that("train and prediction when gctorture is on", {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
context('Test generalized linear models')
|
||||
|
||||
require(xgboost)
|
||||
|
||||
test_that("gblinear works", {
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
data(agaricus.test, package = 'xgboost')
|
||||
@@ -44,31 +46,3 @@ test_that("gblinear works", {
|
||||
expect_equal(dim(h), c(n, ncol(dtrain) + 1))
|
||||
expect_s4_class(h, "dgCMatrix")
|
||||
})
|
||||
|
||||
test_that("gblinear early stopping works", {
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
data(agaricus.test, package = 'xgboost')
|
||||
dtrain <- xgb.DMatrix(agaricus.train$data, label = agaricus.train$label)
|
||||
dtest <- xgb.DMatrix(agaricus.test$data, label = agaricus.test$label)
|
||||
|
||||
param <- list(
|
||||
objective = "binary:logistic", eval_metric = "error", booster = "gblinear",
|
||||
nthread = 2, eta = 0.8, alpha = 0.0001, lambda = 0.0001,
|
||||
updater = "coord_descent"
|
||||
)
|
||||
|
||||
es_round <- 1
|
||||
n <- 10
|
||||
booster <- xgb.train(
|
||||
param, dtrain, n, list(eval = dtest, train = dtrain), early_stopping_rounds = es_round
|
||||
)
|
||||
expect_equal(booster$best_iteration, 5)
|
||||
predt_es <- predict(booster, dtrain)
|
||||
|
||||
n <- booster$best_iteration + es_round
|
||||
booster <- xgb.train(
|
||||
param, dtrain, n, list(eval = dtest, train = dtrain), early_stopping_rounds = es_round
|
||||
)
|
||||
predt <- predict(booster, dtrain)
|
||||
expect_equal(predt_es, predt)
|
||||
})
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
context('Test helper functions')
|
||||
|
||||
VCD_AVAILABLE <- requireNamespace("vcd", quietly = TRUE)
|
||||
.skip_if_vcd_not_available <- function() {
|
||||
if (!VCD_AVAILABLE) {
|
||||
testthat::skip("Optional testing dependency 'vcd' not found.")
|
||||
}
|
||||
}
|
||||
require(xgboost)
|
||||
require(data.table)
|
||||
require(Matrix)
|
||||
require(vcd, quietly = TRUE)
|
||||
|
||||
float_tolerance <- 5e-6
|
||||
|
||||
@@ -13,30 +11,25 @@ float_tolerance <- 5e-6
|
||||
flag_32bit <- .Machine$sizeof.pointer != 8
|
||||
|
||||
set.seed(1982)
|
||||
data(Arthritis)
|
||||
df <- data.table(Arthritis, keep.rownames = FALSE)
|
||||
df[, AgeDiscret := as.factor(round(Age / 10, 0))]
|
||||
df[, AgeCat := as.factor(ifelse(Age > 30, "Old", "Young"))]
|
||||
df[, ID := NULL]
|
||||
sparse_matrix <- sparse.model.matrix(Improved~.-1, data = df) # nolint
|
||||
label <- df[, ifelse(Improved == "Marked", 1, 0)]
|
||||
|
||||
# binary
|
||||
nrounds <- 12
|
||||
if (isTRUE(VCD_AVAILABLE)) {
|
||||
data(Arthritis, package = "vcd")
|
||||
df <- data.table::data.table(Arthritis, keep.rownames = FALSE)
|
||||
df[, AgeDiscret := as.factor(round(Age / 10, 0))]
|
||||
df[, AgeCat := as.factor(ifelse(Age > 30, "Old", "Young"))]
|
||||
df[, ID := NULL]
|
||||
sparse_matrix <- Matrix::sparse.model.matrix(Improved~.-1, data = df) # nolint
|
||||
label <- df[, ifelse(Improved == "Marked", 1, 0)]
|
||||
bst.Tree <- xgboost(data = sparse_matrix, label = label, max_depth = 9,
|
||||
eta = 1, nthread = 2, nrounds = nrounds, verbose = 0,
|
||||
objective = "binary:logistic", booster = "gbtree")
|
||||
|
||||
# binary
|
||||
bst.Tree <- xgboost(data = sparse_matrix, label = label, max_depth = 9,
|
||||
eta = 1, nthread = 2, nrounds = nrounds, verbose = 0,
|
||||
objective = "binary:logistic", booster = "gbtree",
|
||||
base_score = 0.5)
|
||||
bst.GLM <- xgboost(data = sparse_matrix, label = label,
|
||||
eta = 1, nthread = 1, nrounds = nrounds, verbose = 0,
|
||||
objective = "binary:logistic", booster = "gblinear")
|
||||
|
||||
bst.GLM <- xgboost(data = sparse_matrix, label = label,
|
||||
eta = 1, nthread = 1, nrounds = nrounds, verbose = 0,
|
||||
objective = "binary:logistic", booster = "gblinear",
|
||||
base_score = 0.5)
|
||||
|
||||
feature.names <- colnames(sparse_matrix)
|
||||
}
|
||||
feature.names <- colnames(sparse_matrix)
|
||||
|
||||
# multiclass
|
||||
mlabel <- as.numeric(iris$Species) - 1
|
||||
@@ -51,7 +44,6 @@ mbst.GLM <- xgboost(data = as.matrix(iris[, -5]), label = mlabel, verbose = 0,
|
||||
|
||||
|
||||
test_that("xgb.dump works", {
|
||||
.skip_if_vcd_not_available()
|
||||
if (!flag_32bit)
|
||||
expect_length(xgb.dump(bst.Tree), 200)
|
||||
dump_file <- file.path(tempdir(), 'xgb.model.dump')
|
||||
@@ -63,11 +55,10 @@ test_that("xgb.dump works", {
|
||||
dmp <- xgb.dump(bst.Tree, dump_format = "json")
|
||||
expect_length(dmp, 1)
|
||||
if (!flag_32bit)
|
||||
expect_length(grep('nodeid', strsplit(dmp, '\n', fixed = TRUE)[[1]], fixed = TRUE), 188)
|
||||
expect_length(grep('nodeid', strsplit(dmp, '\n')[[1]]), 188)
|
||||
})
|
||||
|
||||
test_that("xgb.dump works for gblinear", {
|
||||
.skip_if_vcd_not_available()
|
||||
expect_length(xgb.dump(bst.GLM), 14)
|
||||
# also make sure that it works properly for a sparse model where some coefficients
|
||||
# are 0 from setting large L1 regularization:
|
||||
@@ -80,11 +71,10 @@ test_that("xgb.dump works for gblinear", {
|
||||
# JSON format
|
||||
dmp <- xgb.dump(bst.GLM.sp, dump_format = "json")
|
||||
expect_length(dmp, 1)
|
||||
expect_length(grep('\\d', strsplit(dmp, '\n', fixed = TRUE)[[1]]), 11)
|
||||
expect_length(grep('\\d', strsplit(dmp, '\n')[[1]]), 11)
|
||||
})
|
||||
|
||||
test_that("predict leafs works", {
|
||||
.skip_if_vcd_not_available()
|
||||
# no error for gbtree
|
||||
expect_error(pred_leaf <- predict(bst.Tree, sparse_matrix, predleaf = TRUE), regexp = NA)
|
||||
expect_equal(dim(pred_leaf), c(nrow(sparse_matrix), nrounds))
|
||||
@@ -93,7 +83,6 @@ test_that("predict leafs works", {
|
||||
})
|
||||
|
||||
test_that("predict feature contributions works", {
|
||||
.skip_if_vcd_not_available()
|
||||
# gbtree binary classifier
|
||||
expect_error(pred_contr <- predict(bst.Tree, sparse_matrix, predcontrib = TRUE), regexp = NA)
|
||||
expect_equal(dim(pred_contr), c(nrow(sparse_matrix), ncol(sparse_matrix) + 1))
|
||||
@@ -180,9 +169,8 @@ test_that("SHAPs sum to predictions, with or without DART", {
|
||||
label = y,
|
||||
nrounds = nrounds)
|
||||
|
||||
pr <- function(...) {
|
||||
pr <- function(...)
|
||||
predict(fit, newdata = d, ...)
|
||||
}
|
||||
pred <- pr()
|
||||
shap <- pr(predcontrib = TRUE)
|
||||
shapi <- pr(predinteraction = TRUE)
|
||||
@@ -197,7 +185,6 @@ test_that("SHAPs sum to predictions, with or without DART", {
|
||||
})
|
||||
|
||||
test_that("xgb-attribute functionality", {
|
||||
.skip_if_vcd_not_available()
|
||||
val <- "my attribute value"
|
||||
list.val <- list(my_attr = val, a = 123, b = 'ok')
|
||||
list.ch <- list.val[order(names(list.val))]
|
||||
@@ -231,17 +218,16 @@ test_that("xgb-attribute functionality", {
|
||||
expect_null(xgb.attributes(bst))
|
||||
})
|
||||
|
||||
if (grepl('Windows', Sys.info()[['sysname']], fixed = TRUE) ||
|
||||
grepl('Linux', Sys.info()[['sysname']], fixed = TRUE) ||
|
||||
grepl('Darwin', Sys.info()[['sysname']], fixed = TRUE)) {
|
||||
if (grepl('Windows', Sys.info()[['sysname']]) ||
|
||||
grepl('Linux', Sys.info()[['sysname']]) ||
|
||||
grepl('Darwin', Sys.info()[['sysname']])) {
|
||||
test_that("xgb-attribute numeric precision", {
|
||||
.skip_if_vcd_not_available()
|
||||
# check that lossless conversion works with 17 digits
|
||||
# numeric -> character -> numeric
|
||||
X <- 10^runif(100, -20, 20)
|
||||
if (capabilities('long.double')) {
|
||||
X2X <- as.numeric(format(X, digits = 17))
|
||||
expect_equal(X, X2X, tolerance = float_tolerance)
|
||||
expect_identical(X, X2X)
|
||||
}
|
||||
# retrieved attributes to be the same as written
|
||||
for (x in X) {
|
||||
@@ -254,7 +240,6 @@ if (grepl('Windows', Sys.info()[['sysname']], fixed = TRUE) ||
|
||||
}
|
||||
|
||||
test_that("xgb.Booster serializing as R object works", {
|
||||
.skip_if_vcd_not_available()
|
||||
saveRDS(bst.Tree, 'xgb.model.rds')
|
||||
bst <- readRDS('xgb.model.rds')
|
||||
dtrain <- xgb.DMatrix(sparse_matrix, label = label)
|
||||
@@ -273,7 +258,6 @@ test_that("xgb.Booster serializing as R object works", {
|
||||
})
|
||||
|
||||
test_that("xgb.model.dt.tree works with and without feature names", {
|
||||
.skip_if_vcd_not_available()
|
||||
names.dt.trees <- c("Tree", "Node", "ID", "Feature", "Split", "Yes", "No", "Missing", "Quality", "Cover")
|
||||
dt.tree <- xgb.model.dt.tree(feature_names = feature.names, model = bst.Tree)
|
||||
expect_equal(names.dt.trees, names(dt.tree))
|
||||
@@ -293,18 +277,16 @@ test_that("xgb.model.dt.tree works with and without feature names", {
|
||||
|
||||
# using integer node ID instead of character
|
||||
dt.tree.int <- xgb.model.dt.tree(model = bst.Tree, use_int_id = TRUE)
|
||||
expect_equal(as.integer(data.table::tstrsplit(dt.tree$Yes, '-', fixed = TRUE)[[2]]), dt.tree.int$Yes)
|
||||
expect_equal(as.integer(data.table::tstrsplit(dt.tree$No, '-', fixed = TRUE)[[2]]), dt.tree.int$No)
|
||||
expect_equal(as.integer(data.table::tstrsplit(dt.tree$Missing, '-', fixed = TRUE)[[2]]), dt.tree.int$Missing)
|
||||
expect_equal(as.integer(tstrsplit(dt.tree$Yes, '-')[[2]]), dt.tree.int$Yes)
|
||||
expect_equal(as.integer(tstrsplit(dt.tree$No, '-')[[2]]), dt.tree.int$No)
|
||||
expect_equal(as.integer(tstrsplit(dt.tree$Missing, '-')[[2]]), dt.tree.int$Missing)
|
||||
})
|
||||
|
||||
test_that("xgb.model.dt.tree throws error for gblinear", {
|
||||
.skip_if_vcd_not_available()
|
||||
expect_error(xgb.model.dt.tree(model = bst.GLM))
|
||||
})
|
||||
|
||||
test_that("xgb.importance works with and without feature names", {
|
||||
.skip_if_vcd_not_available()
|
||||
importance.Tree <- xgb.importance(feature_names = feature.names, model = bst.Tree)
|
||||
if (!flag_32bit)
|
||||
expect_equal(dim(importance.Tree), c(7, 4))
|
||||
@@ -328,50 +310,10 @@ test_that("xgb.importance works with and without feature names", {
|
||||
# for multiclass
|
||||
imp.Tree <- xgb.importance(model = mbst.Tree)
|
||||
expect_equal(dim(imp.Tree), c(4, 4))
|
||||
|
||||
trees <- seq(from = 0, by = 2, length.out = 2)
|
||||
importance <- xgb.importance(feature_names = feature.names, model = bst.Tree, trees = trees)
|
||||
|
||||
importance_from_dump <- function() {
|
||||
model_text_dump <- xgb.dump(model = bst.Tree, with_stats = TRUE, trees = trees)
|
||||
imp <- xgb.model.dt.tree(
|
||||
feature_names = feature.names,
|
||||
text = model_text_dump,
|
||||
trees = trees
|
||||
)[
|
||||
Feature != "Leaf", .(
|
||||
Gain = sum(Quality),
|
||||
Cover = sum(Cover),
|
||||
Frequency = .N
|
||||
),
|
||||
by = Feature
|
||||
][
|
||||
, `:=`(
|
||||
Gain = Gain / sum(Gain),
|
||||
Cover = Cover / sum(Cover),
|
||||
Frequency = Frequency / sum(Frequency)
|
||||
)
|
||||
][
|
||||
order(Gain, decreasing = TRUE)
|
||||
]
|
||||
imp
|
||||
}
|
||||
expect_equal(importance_from_dump(), importance, tolerance = 1e-6)
|
||||
|
||||
## decision stump
|
||||
m <- xgboost::xgboost(
|
||||
data = as.matrix(data.frame(x = c(0, 1))),
|
||||
label = c(1, 2),
|
||||
nrounds = 1,
|
||||
base_score = 0.5
|
||||
)
|
||||
df <- xgb.model.dt.tree(model = m)
|
||||
expect_equal(df$Feature, "Leaf")
|
||||
expect_equal(df$Cover, 2)
|
||||
xgb.importance(model = mbst.Tree, trees = seq(from = 0, by = nclass, length.out = nrounds))
|
||||
})
|
||||
|
||||
test_that("xgb.importance works with GLM model", {
|
||||
.skip_if_vcd_not_available()
|
||||
importance.GLM <- xgb.importance(feature_names = feature.names, model = bst.GLM)
|
||||
expect_equal(dim(importance.GLM), c(10, 2))
|
||||
expect_equal(colnames(importance.GLM), c("Feature", "Weight"))
|
||||
@@ -387,7 +329,6 @@ test_that("xgb.importance works with GLM model", {
|
||||
})
|
||||
|
||||
test_that("xgb.model.dt.tree and xgb.importance work with a single split model", {
|
||||
.skip_if_vcd_not_available()
|
||||
bst1 <- xgboost(data = sparse_matrix, label = label, max_depth = 1,
|
||||
eta = 1, nthread = 2, nrounds = 1, verbose = 0,
|
||||
objective = "binary:logistic")
|
||||
@@ -399,19 +340,16 @@ test_that("xgb.model.dt.tree and xgb.importance work with a single split model",
|
||||
})
|
||||
|
||||
test_that("xgb.plot.tree works with and without feature names", {
|
||||
.skip_if_vcd_not_available()
|
||||
expect_silent(xgb.plot.tree(feature_names = feature.names, model = bst.Tree))
|
||||
expect_silent(xgb.plot.tree(model = bst.Tree))
|
||||
})
|
||||
|
||||
test_that("xgb.plot.multi.trees works with and without feature names", {
|
||||
.skip_if_vcd_not_available()
|
||||
xgb.plot.multi.trees(model = bst.Tree, feature_names = feature.names, features_keep = 3)
|
||||
xgb.plot.multi.trees(model = bst.Tree, features_keep = 3)
|
||||
})
|
||||
|
||||
test_that("xgb.plot.deepness works", {
|
||||
.skip_if_vcd_not_available()
|
||||
d2p <- xgb.plot.deepness(model = bst.Tree)
|
||||
expect_equal(colnames(d2p), c("ID", "Tree", "Depth", "Cover", "Weight"))
|
||||
xgb.plot.deepness(model = bst.Tree, which = "med.depth")
|
||||
@@ -419,7 +357,6 @@ test_that("xgb.plot.deepness works", {
|
||||
})
|
||||
|
||||
test_that("xgb.shap.data works when top_n is provided", {
|
||||
.skip_if_vcd_not_available()
|
||||
data_list <- xgb.shap.data(data = sparse_matrix, model = bst.Tree, top_n = 2)
|
||||
expect_equal(names(data_list), c("data", "shap_contrib"))
|
||||
expect_equal(NCOL(data_list$data), 2)
|
||||
@@ -437,14 +374,12 @@ test_that("xgb.shap.data works when top_n is provided", {
|
||||
})
|
||||
|
||||
test_that("xgb.shap.data works with subsampling", {
|
||||
.skip_if_vcd_not_available()
|
||||
data_list <- xgb.shap.data(data = sparse_matrix, model = bst.Tree, top_n = 2, subsample = 0.8)
|
||||
expect_equal(NROW(data_list$data), as.integer(0.8 * nrow(sparse_matrix)))
|
||||
expect_equal(NROW(data_list$data), NROW(data_list$shap_contrib))
|
||||
})
|
||||
|
||||
test_that("prepare.ggplot.shap.data works", {
|
||||
.skip_if_vcd_not_available()
|
||||
data_list <- xgb.shap.data(data = sparse_matrix, model = bst.Tree, top_n = 2)
|
||||
plot_data <- prepare.ggplot.shap.data(data_list, normalize = TRUE)
|
||||
expect_s3_class(plot_data, "data.frame")
|
||||
@@ -455,19 +390,17 @@ test_that("prepare.ggplot.shap.data works", {
|
||||
})
|
||||
|
||||
test_that("xgb.plot.shap works", {
|
||||
.skip_if_vcd_not_available()
|
||||
sh <- xgb.plot.shap(data = sparse_matrix, model = bst.Tree, top_n = 2, col = 4)
|
||||
expect_equal(names(sh), c("data", "shap_contrib"))
|
||||
})
|
||||
|
||||
test_that("xgb.plot.shap.summary works", {
|
||||
.skip_if_vcd_not_available()
|
||||
expect_silent(xgb.plot.shap.summary(data = sparse_matrix, model = bst.Tree, top_n = 2))
|
||||
expect_silent(xgb.ggplot.shap.summary(data = sparse_matrix, model = bst.Tree, top_n = 2))
|
||||
})
|
||||
|
||||
test_that("check.deprecation works", {
|
||||
ttt <- function(a = NNULL, DUMMY = NULL, ...) {
|
||||
ttt <- function(a = NNULL, DUMMY=NULL, ...) {
|
||||
check.deprecation(...)
|
||||
as.list((environment()))
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ test_that("interaction constraints for regression", {
|
||||
|
||||
# Set all observations to have the same x3 values then increment
|
||||
# by the same amount
|
||||
preds <- lapply(c(1, 2, 3), function(x) {
|
||||
preds <- lapply(c(1, 2, 3), function(x){
|
||||
tmat <- matrix(c(x1, x2, rep(x, 1000)), ncol = 3)
|
||||
return(predict(bst, tmat))
|
||||
})
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
context('Test prediction of feature interactions')
|
||||
|
||||
require(xgboost)
|
||||
|
||||
set.seed(123)
|
||||
|
||||
test_that("predict feature interactions works", {
|
||||
@@ -155,28 +157,3 @@ test_that("multiclass feature interactions work", {
|
||||
# sums WRT columns must be close to feature contributions
|
||||
expect_lt(max(abs(apply(intr, c(1, 2, 3), sum) - aperm(cont, c(3, 1, 2)))), 0.00001)
|
||||
})
|
||||
|
||||
|
||||
test_that("SHAP single sample works", {
|
||||
train <- agaricus.train
|
||||
test <- agaricus.test
|
||||
booster <- xgboost(
|
||||
data = train$data,
|
||||
label = train$label,
|
||||
max_depth = 2,
|
||||
nrounds = 4,
|
||||
objective = "binary:logistic",
|
||||
)
|
||||
|
||||
predt <- predict(
|
||||
booster,
|
||||
newdata = train$data[1, , drop = FALSE], predcontrib = TRUE
|
||||
)
|
||||
expect_equal(dim(predt), c(1, dim(train$data)[2] + 1))
|
||||
|
||||
predt <- predict(
|
||||
booster,
|
||||
newdata = train$data[1, , drop = FALSE], predinteraction = TRUE
|
||||
)
|
||||
expect_equal(dim(predt), c(1, dim(train$data)[2] + 1, dim(train$data)[2] + 1))
|
||||
})
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
context("Test model IO.")
|
||||
|
||||
data(agaricus.train, package = "xgboost")
|
||||
data(agaricus.test, package = "xgboost")
|
||||
train <- agaricus.train
|
||||
test <- agaricus.test
|
||||
|
||||
test_that("load/save raw works", {
|
||||
nrounds <- 8
|
||||
booster <- xgboost(
|
||||
data = train$data, label = train$label,
|
||||
nrounds = nrounds, objective = "binary:logistic"
|
||||
)
|
||||
|
||||
json_bytes <- xgb.save.raw(booster, raw_format = "json")
|
||||
ubj_bytes <- xgb.save.raw(booster, raw_format = "ubj")
|
||||
old_bytes <- xgb.save.raw(booster, raw_format = "deprecated")
|
||||
|
||||
from_json <- xgb.load.raw(json_bytes, as_booster = TRUE)
|
||||
from_ubj <- xgb.load.raw(ubj_bytes, as_booster = TRUE)
|
||||
|
||||
json2old <- xgb.save.raw(from_json, raw_format = "deprecated")
|
||||
ubj2old <- xgb.save.raw(from_ubj, raw_format = "deprecated")
|
||||
|
||||
expect_equal(json2old, ubj2old)
|
||||
expect_equal(json2old, old_bytes)
|
||||
})
|
||||
@@ -1,3 +1,6 @@
|
||||
require(xgboost)
|
||||
require(jsonlite)
|
||||
|
||||
context("Models from previous versions of XGBoost can be loaded")
|
||||
|
||||
metadata <- list(
|
||||
@@ -59,12 +62,11 @@ test_that("Models from previous versions of XGBoost can be loaded", {
|
||||
bucket <- 'xgboost-ci-jenkins-artifacts'
|
||||
region <- 'us-west-2'
|
||||
file_name <- 'xgboost_r_model_compatibility_test.zip'
|
||||
zipfile <- tempfile(fileext = ".zip")
|
||||
extract_dir <- tempdir()
|
||||
zipfile <- file.path(getwd(), file_name)
|
||||
model_dir <- file.path(getwd(), 'models')
|
||||
download.file(paste('https://', bucket, '.s3-', region, '.amazonaws.com/', file_name, sep = ''),
|
||||
destfile = zipfile, mode = 'wb', quiet = TRUE)
|
||||
unzip(zipfile, exdir = extract_dir, overwrite = TRUE)
|
||||
model_dir <- file.path(extract_dir, 'models')
|
||||
unzip(zipfile, overwrite = TRUE)
|
||||
|
||||
pred_data <- xgb.DMatrix(matrix(c(0, 0, 0, 0), nrow = 1, ncol = 4))
|
||||
|
||||
@@ -75,21 +77,34 @@ test_that("Models from previous versions of XGBoost can be loaded", {
|
||||
model_xgb_ver <- m[2]
|
||||
name <- m[3]
|
||||
is_rds <- endsWith(model_file, '.rds')
|
||||
is_json <- endsWith(model_file, '.json')
|
||||
# Expect an R warning when a model is loaded from RDS and it was generated by version < 1.1.x
|
||||
if (is_rds && compareVersion(model_xgb_ver, '1.1.1.1') < 0) {
|
||||
booster <- readRDS(model_file)
|
||||
expect_warning(predict(booster, newdata = pred_data))
|
||||
booster <- readRDS(model_file)
|
||||
expect_warning(run_booster_check(booster, name))
|
||||
} else {
|
||||
if (is_rds) {
|
||||
|
||||
cpp_warning <- capture.output({
|
||||
# Expect an R warning when a model is loaded from RDS and it was generated by version < 1.1.x
|
||||
if (is_rds && compareVersion(model_xgb_ver, '1.1.1.1') < 0) {
|
||||
booster <- readRDS(model_file)
|
||||
expect_warning(predict(booster, newdata = pred_data))
|
||||
booster <- readRDS(model_file)
|
||||
expect_warning(run_booster_check(booster, name))
|
||||
} else {
|
||||
booster <- xgb.load(model_file)
|
||||
if (is_rds) {
|
||||
booster <- readRDS(model_file)
|
||||
} else {
|
||||
booster <- xgb.load(model_file)
|
||||
}
|
||||
predict(booster, newdata = pred_data)
|
||||
run_booster_check(booster, name)
|
||||
}
|
||||
predict(booster, newdata = pred_data)
|
||||
run_booster_check(booster, name)
|
||||
})
|
||||
if (compareVersion(model_xgb_ver, '1.0.0.0') < 0) {
|
||||
# Expect a C++ warning when a model was generated in version < 1.0.x
|
||||
m <- grepl(paste0('.*Loading model from XGBoost < 1\\.0\\.0, consider saving it again for ',
|
||||
'improved compatibility.*'), cpp_warning, perl = TRUE)
|
||||
expect_true(length(m) > 0 && all(m))
|
||||
} else if (is_rds && model_xgb_ver == '1.1.1.1') {
|
||||
# Expect a C++ warning when a model is loaded from RDS and it was generated by version 1.1.x
|
||||
m <- grepl(paste0('.*Attempted to load internal configuration for a model file that was ',
|
||||
'generated by a previous version of XGBoost.*'), cpp_warning, perl = TRUE)
|
||||
expect_true(length(m) > 0 && all(m))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require(xgboost)
|
||||
|
||||
context("monotone constraints")
|
||||
|
||||
set.seed(1024)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
context('Test model params and call are exposed to R')
|
||||
|
||||
require(xgboost)
|
||||
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
data(agaricus.test, package = 'xgboost')
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
context('Test Poisson regression model')
|
||||
|
||||
require(xgboost)
|
||||
set.seed(1994)
|
||||
|
||||
test_that("Poisson regression works", {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
require(xgboost)
|
||||
require(Matrix)
|
||||
|
||||
context('Learning to rank')
|
||||
|
||||
test_that('Test ranking with unweighted data', {
|
||||
X <- Matrix::sparseMatrix(
|
||||
i = c(2, 3, 7, 9, 12, 15, 17, 18)
|
||||
, j = c(1, 1, 2, 2, 3, 3, 4, 4)
|
||||
, x = rep(1.0, 8)
|
||||
, dims = c(20, 4)
|
||||
)
|
||||
X <- sparseMatrix(i = c(2, 3, 7, 9, 12, 15, 17, 18),
|
||||
j = c(1, 1, 2, 2, 3, 3, 4, 4),
|
||||
x = rep(1.0, 8), dims = c(20, 4))
|
||||
y <- c(0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0)
|
||||
group <- c(5, 5, 5, 5)
|
||||
dtrain <- xgb.DMatrix(X, label = y, group = group)
|
||||
@@ -20,12 +20,9 @@ test_that('Test ranking with unweighted data', {
|
||||
})
|
||||
|
||||
test_that('Test ranking with weighted data', {
|
||||
X <- Matrix::sparseMatrix(
|
||||
i = c(2, 3, 7, 9, 12, 15, 17, 18)
|
||||
, j = c(1, 1, 2, 2, 3, 3, 4, 4)
|
||||
, x = rep(1.0, 8)
|
||||
, dims = c(20, 4)
|
||||
)
|
||||
X <- sparseMatrix(i = c(2, 3, 7, 9, 12, 15, 17, 18),
|
||||
j = c(1, 1, 2, 2, 3, 3, 4, 4),
|
||||
x = rep(1.0, 8), dims = c(20, 4))
|
||||
y <- c(0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0)
|
||||
group <- c(5, 5, 5, 5)
|
||||
weight <- c(1.0, 2.0, 3.0, 4.0)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require(xgboost)
|
||||
|
||||
context("update trees in an existing model")
|
||||
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
@@ -13,10 +15,7 @@ test_that("updating the model works", {
|
||||
watchlist <- list(train = dtrain, test = dtest)
|
||||
|
||||
# no-subsampling
|
||||
p1 <- list(
|
||||
objective = "binary:logistic", max_depth = 2, eta = 0.05, nthread = 2,
|
||||
updater = "grow_colmaker,prune"
|
||||
)
|
||||
p1 <- list(objective = "binary:logistic", max_depth = 2, eta = 0.05, nthread = 2)
|
||||
set.seed(11)
|
||||
bst1 <- xgb.train(p1, dtrain, nrounds = 10, watchlist, verbose = 0)
|
||||
tr1 <- xgb.model.dt.tree(model = bst1)
|
||||
|
||||
@@ -28,9 +28,7 @@ Package loading:
|
||||
require(xgboost)
|
||||
require(Matrix)
|
||||
require(data.table)
|
||||
if (!require('vcd')) {
|
||||
install.packages('vcd')
|
||||
}
|
||||
if (!require('vcd')) install.packages('vcd')
|
||||
```
|
||||
|
||||
> **VCD** package is used for one of its embedded dataset only.
|
||||
@@ -102,7 +100,7 @@ Note that we transform it to `factor` so the algorithm treat these age groups as
|
||||
Therefore, 20 is not closer to 30 than 60. To make it short, the distance between ages is lost in this transformation.
|
||||
|
||||
```{r}
|
||||
head(df[, AgeDiscret := as.factor(round(Age / 10, 0))])
|
||||
head(df[,AgeDiscret := as.factor(round(Age/10,0))])
|
||||
```
|
||||
|
||||
##### Random split into two groups
|
||||
@@ -110,7 +108,7 @@ head(df[, AgeDiscret := as.factor(round(Age / 10, 0))])
|
||||
Following is an even stronger simplification of the real age with an arbitrary split at 30 years old. We choose this value **based on nothing**. We will see later if simplifying the information based on arbitrary values is a good strategy (you may already have an idea of how well it will work...).
|
||||
|
||||
```{r}
|
||||
head(df[, AgeCat := as.factor(ifelse(Age > 30, "Old", "Young"))])
|
||||
head(df[,AgeCat:= as.factor(ifelse(Age > 30, "Old", "Young"))])
|
||||
```
|
||||
|
||||
##### Risks in adding correlated features
|
||||
@@ -126,13 +124,13 @@ Fortunately, decision tree algorithms (including boosted trees) are very robust
|
||||
We remove ID as there is nothing to learn from this feature (it would just add some noise).
|
||||
|
||||
```{r, results='hide'}
|
||||
df[, ID := NULL]
|
||||
df[,ID:=NULL]
|
||||
```
|
||||
|
||||
We will list the different values for the column `Treatment`:
|
||||
|
||||
```{r}
|
||||
levels(df[, Treatment])
|
||||
levels(df[,Treatment])
|
||||
```
|
||||
|
||||
|
||||
@@ -140,7 +138,7 @@ levels(df[, Treatment])
|
||||
|
||||
Next step, we will transform the categorical data to dummy variables.
|
||||
Several encoding methods exist, e.g., [one-hot encoding](https://en.wikipedia.org/wiki/One-hot) is a common approach.
|
||||
We will use the [dummy contrast coding](https://stats.oarc.ucla.edu/r/library/r-library-contrast-coding-systems-for-categorical-variables/) which is popular because it produces "full rank" encoding (also see [this blog post by Max Kuhn](http://appliedpredictivemodeling.com/blog/2013/10/23/the-basics-of-encoding-categorical-data-for-predictive-models)).
|
||||
We will use the [dummy contrast coding](https://stats.idre.ucla.edu/r/library/r-library-contrast-coding-systems-for-categorical-variables/) which is popular because it produces "full rank" encoding (also see [this blog post by Max Kuhn](http://appliedpredictivemodeling.com/blog/2013/10/23/the-basics-of-encoding-categorical-data-for-predictive-models)).
|
||||
|
||||
The purpose is to transform each value of each *categorical* feature into a *binary* feature `{0, 1}`.
|
||||
|
||||
@@ -149,7 +147,7 @@ For example, the column `Treatment` will be replaced by two columns, `TreatmentP
|
||||
Column `Improved` is excluded because it will be our `label` column, the one we want to predict.
|
||||
|
||||
```{r, warning=FALSE,message=FALSE}
|
||||
sparse_matrix <- sparse.model.matrix(Improved ~ ., data = df)[, -1]
|
||||
sparse_matrix <- sparse.model.matrix(Improved ~ ., data = df)[,-1]
|
||||
head(sparse_matrix)
|
||||
```
|
||||
|
||||
@@ -158,7 +156,7 @@ head(sparse_matrix)
|
||||
Create the output `numeric` vector (not as a sparse `Matrix`):
|
||||
|
||||
```{r}
|
||||
output_vector <- df[, Improved] == "Marked"
|
||||
output_vector = df[,Improved] == "Marked"
|
||||
```
|
||||
|
||||
1. set `Y` vector to `0`;
|
||||
@@ -172,7 +170,7 @@ The code below is very usual. For more information, you can look at the document
|
||||
|
||||
```{r}
|
||||
bst <- xgboost(data = sparse_matrix, label = output_vector, max_depth = 4,
|
||||
eta = 1, nthread = 2, nrounds = 10, objective = "binary:logistic")
|
||||
eta = 1, nthread = 2, nrounds = 10,objective = "binary:logistic")
|
||||
|
||||
```
|
||||
|
||||
@@ -221,7 +219,7 @@ For that purpose we will execute the same function as above but using two more p
|
||||
importanceRaw <- xgb.importance(feature_names = colnames(sparse_matrix), model = bst, data = sparse_matrix, label = output_vector)
|
||||
|
||||
# Cleaning for better display
|
||||
importanceClean <- importanceRaw[, `:=`(Cover = NULL, Frequency = NULL)]
|
||||
importanceClean <- importanceRaw[,`:=`(Cover=NULL, Frequency=NULL)]
|
||||
|
||||
head(importanceClean)
|
||||
```
|
||||
@@ -323,31 +321,16 @@ If you want to try Random Forests algorithm, you can tweak XGBoost parameters!
|
||||
For instance, to compute a model with 1000 trees, with a 0.5 factor on sampling rows and columns:
|
||||
|
||||
```{r, warning=FALSE, message=FALSE}
|
||||
data(agaricus.train, package = 'xgboost')
|
||||
data(agaricus.test, package = 'xgboost')
|
||||
data(agaricus.train, package='xgboost')
|
||||
data(agaricus.test, package='xgboost')
|
||||
train <- agaricus.train
|
||||
test <- agaricus.test
|
||||
|
||||
#Random Forest - 1000 trees
|
||||
bst <- xgboost(
|
||||
data = train$data
|
||||
, label = train$label
|
||||
, max_depth = 4
|
||||
, num_parallel_tree = 1000
|
||||
, subsample = 0.5
|
||||
, colsample_bytree = 0.5
|
||||
, nrounds = 1
|
||||
, objective = "binary:logistic"
|
||||
)
|
||||
bst <- xgboost(data = train$data, label = train$label, max_depth = 4, num_parallel_tree = 1000, subsample = 0.5, colsample_bytree =0.5, nrounds = 1, objective = "binary:logistic")
|
||||
|
||||
#Boosting - 3 rounds
|
||||
bst <- xgboost(
|
||||
data = train$data
|
||||
, label = train$label
|
||||
, max_depth = 4
|
||||
, nrounds = 3
|
||||
, objective = "binary:logistic"
|
||||
)
|
||||
bst <- xgboost(data = train$data, label = train$label, max_depth = 4, nrounds = 3, objective = "binary:logistic")
|
||||
```
|
||||
|
||||
> Note that the parameter `round` is set to `1`.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user